基于SSM框架的服装企业供应链数字化平台
项目背景与业务痛点
传统服装行业在商品流转过程中面临诸多挑战:库存数据更新滞后导致超卖或缺货现象频发,手工记录销售数据容易出错且难以进行深度分析,采购决策缺乏数据支撑造成资金占用不合理。这些痛点直接影响企业的运营效率和市场竞争力。
本系统采用SSM(Spring + Spring MVC + MyBatis)技术栈,构建了一套完整的供应链数字化解决方案。系统通过业务流程的数字化重构,实现了从采购入库、库存管理到销售出库的全链路闭环管理,为服装企业提供实时、准确的业务数据支撑。
技术架构设计
分层架构实现
系统采用经典的三层架构设计,各层职责分明:
表现层基于Spring MVC框架,通过注解驱动的控制器处理前端请求:
@Controller
@RequestMapping("/inventory")
public class InventoryController {
@Autowired
private InventoryService inventoryService;
@RequestMapping(value = "/update", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<Map<String, Object>> updateInventory(
@RequestBody InventoryUpdateDTO updateDTO) {
try {
inventoryService.updateStockQuantity(updateDTO);
return ResponseEntity.ok(Collections.singletonMap("success", true));
} catch (BusinessException e) {
return ResponseEntity.badRequest()
.body(Collections.singletonMap("error", e.getMessage()));
}
}
}
业务逻辑层使用Spring的IoC容器管理服务组件,通过声明式事务确保数据一致性:
@Service
@Transactional
public class InventoryServiceImpl implements InventoryService {
@Autowired
private InventoryMapper inventoryMapper;
@Override
public void updateStockQuantity(InventoryUpdateDTO updateDTO) {
// 库存检查
Inventory current = inventoryMapper.selectByProductId(updateDTO.getProductId());
if (current.getQuantity() + updateDTO.getChangeAmount() < 0) {
throw new BusinessException("库存数量不足");
}
// 更新库存
inventoryMapper.updateQuantity(updateDTO);
// 记录库存变更日志
inventoryMapper.insertInventoryLog(createInventoryLog(updateDTO));
}
}
数据访问层基于MyBatis实现,通过XML映射文件定义复杂的SQL查询:
<!-- 库存查询映射 -->
<select id="selectInventoryWithProductInfo" resultMap="InventoryResultMap">
SELECT i.*, p.product_name, p.category_id, p.specifications
FROM inventory i
LEFT JOIN product p ON i.product_id = p.id
WHERE 1=1
<if test="categoryId != null">
AND p.category_id = #{categoryId}
</if>
<if test="warehouseId != null">
AND i.warehouse_id = #{warehouseId}
</if>
<if test="minQuantity != null">
AND i.quantity >= #{minQuantity}
</if>
ORDER BY i.update_time DESC
LIMIT #{offset}, #{pageSize}
</select>
安全与配置管理
系统通过Spring Security实现权限控制,确保不同角色只能访问授权资源:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/warehouse/**").hasAnyRole("ADMIN", "WAREHOUSE_MANAGER")
.antMatchers("/sales/**").hasAnyRole("ADMIN", "SALES_STAFF")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.permitAll();
}
}
数据库架构深度解析
核心表结构设计
**商品信息表(product)**的设计体现了服装行业的特殊性:
CREATE TABLE product (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
product_code VARCHAR(50) UNIQUE NOT NULL COMMENT '商品编码',
product_name VARCHAR(100) NOT NULL COMMENT '商品名称',
category_id INT NOT NULL COMMENT '分类ID',
specifications JSON NOT NULL COMMENT '规格属性(颜色、尺码等)',
purchase_price DECIMAL(10,2) COMMENT '采购价',
retail_price DECIMAL(10,2) COMMENT '零售价',
supplier_id BIGINT COMMENT '供应商ID',
status TINYINT DEFAULT 1 COMMENT '状态:1-正常,0-停用',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_category (category_id),
INDEX idx_supplier (supplier_id),
INDEX idx_status (status)
) COMMENT='商品信息表';
该表设计的亮点在于使用JSON类型存储规格属性,有效解决了服装产品多规格(颜色、尺码、材质)的灵活存储需求,避免了传统EAV模式带来的查询复杂度。
**库存管理表(inventory)**采用实时库存与安全库存分离的设计:
CREATE TABLE inventory (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
product_id BIGINT NOT NULL COMMENT '商品ID',
warehouse_id INT NOT NULL COMMENT '仓库ID',
quantity INT NOT NULL DEFAULT 0 COMMENT '当前库存数量',
reserved_quantity INT DEFAULT 0 COMMENT '预占数量',
safe_stock_level INT DEFAULT 0 COMMENT '安全库存水平',
lock_version INT DEFAULT 0 COMMENT '乐观锁版本',
last_stocktake_date DATE COMMENT '最后盘点日期',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_product_warehouse (product_id, warehouse_id),
INDEX idx_warehouse (warehouse_id),
INDEX idx_quantity (quantity)
) COMMENT='库存表';
该表通过lock_version字段实现乐观锁机制,防止高并发场景下的库存超卖问题。reserved_quantity字段有效区分了实际库存与已预订库存,为销售订单处理提供了数据基础。
**销售订单表(sales_order)**支持复杂的订单状态流转:
CREATE TABLE sales_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_number VARCHAR(50) UNIQUE NOT NULL COMMENT '订单编号',
customer_id BIGINT COMMENT '客户ID',
total_amount DECIMAL(12,2) NOT NULL COMMENT '订单总金额',
actual_amount DECIMAL(12,2) COMMENT '实收金额',
order_status TINYINT NOT NULL COMMENT '订单状态:1-待付款,2-已付款,3-配送中,4-已完成,5-已取消',
payment_method TINYINT COMMENT '支付方式:1-现金,2-刷卡,3-移动支付',
warehouse_id INT NOT NULL COMMENT '出货仓库',
salesperson_id BIGINT NOT NULL COMMENT '销售人员ID',
order_notes TEXT COMMENT '订单备注',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_order_number (order_number),
INDEX idx_customer (customer_id),
INDEX idx_status (order_status),
INDEX idx_create_time (create_time)
) COMMENT='销售订单表';
实体关系映射
通过MyBatis的ResultMap实现复杂的对象关系映射:
<resultMap id="SalesOrderDetailMap" type="com.apparel.entity.SalesOrderDetail">
<id column="id" property="id"/>
<result column="order_id" property="orderId"/>
<result column="product_id" property="productId"/>
<result column="quantity" property="quantity"/>
<result column="unit_price" property="unitPrice"/>
<result column="subtotal" property="subtotal"/>
<association property="product" javaType="com.apparel.entity.Product">
<id column="product_id" property="id"/>
<result column="product_name" property="productName"/>
<result column="product_code" property="productCode"/>
</association>
</resultMap>
核心功能模块深度解析
智能库存管理
库存管理模块实现了多维度库存监控和预警机制。系统通过实时库存追踪和安全库存设置,自动生成补货建议。

库存查询服务的实现采用了动态SQL构建,支持多条件组合查询:
@Service
public class InventoryQueryService {
public PageInfo<InventoryVO> queryInventory(InventoryQueryDTO queryDTO) {
PageHelper.startPage(queryDTO.getPageNum(), queryDTO.getPageSize());
List<InventoryVO> inventoryList = inventoryMapper.selectByConditions(queryDTO);
return new PageInfo<>(inventoryList);
}
public List<InventoryAlertVO> getInventoryAlerts() {
return inventoryMapper.selectLowStockProducts();
}
}
对应的Mapper XML文件实现了复杂的库存查询逻辑:
<select id="selectByConditions" resultType="com.apparel.vo.InventoryVO">
SELECT
i.*,
p.product_name,
p.product_code,
w.warehouse_name,
c.category_name
FROM inventory i
INNER JOIN product p ON i.product_id = p.id
INNER JOIN warehouse w ON i.warehouse_id = w.id
LEFT JOIN category c ON p.category_id = c.id
<where>
<if test="warehouseId != null">AND i.warehouse_id = #{warehouseId}</if>
<if test="categoryId != null">AND p.category_id = #{categoryId}</if>
<if test="productCode != null and productCode != ''">
AND p.product_code LIKE CONCAT('%', #{productCode}, '%')
</if>
<if test="lowStockOnly">
AND i.quantity <= i.safe_stock_level
</if>
</where>
ORDER BY i.quantity ASC
</select>
采购入库流程
采购入库模块实现了从采购计划到实物入库的全流程管理,支持批量入库和库存即时更新。

入库业务的实现采用了事务管理确保数据一致性:
@Service
@Transactional(rollbackFor = Exception.class)
public class PurchaseService {
public void processInbound(PurchaseOrder order, List<InboundItem> items) {
// 验证采购单状态
validatePurchaseOrder(order);
// 处理每个入库项
for (InboundItem item : items) {
processInboundItem(order, item);
}
// 更新采购单状态
updatePurchaseOrderStatus(order, PurchaseStatus.COMPLETED);
// 记录操作日志
logInboundOperation(order, items);
}
private void processInboundItem(PurchaseOrder order, InboundItem item) {
// 检查商品信息
Product product = productMapper.selectById(item.getProductId());
if (product == null) {
throw new BusinessException("商品不存在: " + item.getProductId());
}
// 更新库存
Inventory inventory = inventoryMapper.selectByProductAndWarehouse(
item.getProductId(), order.getWarehouseId());
if (inventory == null) {
// 新建库存记录
inventory = createNewInventory(item, order.getWarehouseId());
inventoryMapper.insert(inventory);
} else {
// 更新现有库存
inventory.setQuantity(inventory.getQuantity() + item.getQuantity());
inventoryMapper.updateQuantity(inventory);
}
// 记录入库明细
InboundDetail detail = createInboundDetail(order, item, inventory);
inboundDetailMapper.insert(detail);
}
}
销售出库管理
销售模块支持快速开单、库存预占和出库核销,确保销售数据与库存数据的实时同步。

销售出库的核心业务逻辑实现了库存的原子性操作:
@Service
public class SalesService {
@Transactional
public SalesOrder createSalesOrder(SalesOrderDTO orderDTO) {
// 创建订单基础信息
SalesOrder order = buildSalesOrder(orderDTO);
salesOrderMapper.insert(order);
// 处理订单明细
BigDecimal totalAmount = BigDecimal.ZERO;
for (SalesOrderItemDTO itemDTO : orderDTO.getItems()) {
SalesOrderItem item = processOrderItem(order, itemDTO);
totalAmount = totalAmount.add(item.getSubtotal());
}
// 更新订单总金额
order.setTotalAmount(totalAmount);
salesOrderMapper.updateAmount(order);
return order;
}
private SalesOrderItem processOrderItem(SalesOrder order, SalesOrderItemDTO itemDTO) {
// 检查库存可用性
Inventory inventory = inventoryMapper.selectForUpdate(
itemDTO.getProductId(), order.getWarehouseId());
if (inventory.getAvailableQuantity() < itemDTO.getQuantity()) {
throw new BusinessException("库存不足,商品ID: " + itemDTO.getProductId());
}
// 预占库存
inventory.setReservedQuantity(
inventory.getReservedQuantity() + itemDTO.getQuantity());
inventoryMapper.updateReservedQuantity(inventory);
// 创建订单明细
SalesOrderItem item = buildOrderItem(order, itemDTO, inventory);
salesOrderItemMapper.insert(item);
return item;
}
}
商品SKU管理
商品管理模块支持多维度的SKU属性管理,通过灵活的规格配置满足服装行业的复杂需求。

商品规格的JSON处理采用了自定义类型处理器:
public class SpecificationsTypeHandler extends BaseTypeHandler<Map<String, Object>> {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
Map<String, Object> parameter, JdbcType jdbcType) {
try {
ps.setString(i, objectMapper.writeValueAsString(parameter));
} catch (JsonProcessingException e) {
throw new RuntimeException("规格数据序列化失败", e);
}
}
@Override
public Map<String, Object> getNullableResult(ResultSet rs, String columnName) {
return parseSpecifications(rs.getString(columnName));
}
private Map<String, Object> parseSpecifications(String json) {
if (json == null || json.trim().isEmpty()) {
return new HashMap<>();
}
try {
return objectMapper.readValue(json,
new TypeReference<Map<String, Object>>() {});
} catch (IOException e) {
throw new RuntimeException("规格数据解析失败", e);
}
}
}
系统性能优化策略
数据库查询优化
通过索引优化和查询重构提升系统响应速度:
-- 为高频查询字段创建复合索引
CREATE INDEX idx_inventory_query ON inventory(warehouse_id, product_id, quantity);
CREATE INDEX idx_sales_time ON sales_order(create_time, order_status);
CREATE INDEX idx_product_category ON product(category_id, status);
-- 使用覆盖索引避免回表查询
CREATE INDEX idx_inventory_cover ON inventory(warehouse_id, product_id, quantity, update_time);
缓存策略实施
采用Redis作为缓存层,减少数据库访问压力:
@Service
public class ProductCacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String PRODUCT_KEY_PREFIX = "product:";
private static final Duration CACHE_DURATION = Duration.ofHours(2);
public Product getProductById(Long productId) {
String cacheKey = PRODUCT_KEY_PREFIX + productId;
Product product = (Product) redisTemplate.opsForValue().get(cacheKey);
if (product == null) {
product = productMapper.selectById(productId);
if (product != null) {
redisTemplate.opsForValue().set(cacheKey, product, CACHE_DURATION);
}
}
return product;
}
public void evictProductCache(Long productId) {
String cacheKey = PRODUCT_KEY_PREFIX + productId;
redisTemplate.delete(cacheKey);
}
}
未来功能扩展方向
智能预测与补货建议
基于历史销售数据的机器学习算法实现需求预测:
@Service
public class DemandForecastService {
public List<ReplenishmentRecommendation> generateRecommendations() {
// 获取历史销售数据
List<SalesData> salesHistory = salesMapper.selectSalesTrend(180);
// 应用预测模型(可集成第三方机器学习服务)
return forecastingModel.predictReplenishment(salesHistory);
}
}
移动端应用扩展
开发响应式前端或独立的移动APP,支持仓库扫码作业:
// 移动端入库扫描功能
class MobileInboundScanner {
async processBarcodeScan(barcodeData) {
try {
const productInfo = await this.lookupProduct(barcodeData);
const inventoryInfo = await this.checkInventory(productInfo.id);
return {
product: productInfo,
inventory: inventoryInfo,
suggestedLocation: this.calculateStorageLocation(productInfo)
};
} catch (error) {
console.error('扫码处理失败:', error);
throw error;
}
}
}
供应链协同平台
构建供应商门户,实现采购订单的在线协同:
@Service
public class SupplierPortalService {
public void sharePurchaseOrderWithSupplier(Long orderId, Long supplierId) {
PurchaseOrder order = purchaseOrderMapper.selectById(orderId);
Supplier supplier = supplierMapper.selectById(supplierId);
// 生成供应商可视化的订单信息
SupplierOrderView view = buildSupplierView(order, supplier);
// 通过消息队列异步通知供应商
messageQueue.sendSupplierNotification(supplier.getContactEmail(), view);
}
}
实时数据大屏
基于WebSocket技术实现管理驾驶舱的实时数据展示:
@ServerEndpoint("/dashboard/websocket")
@Component
public class DashboardWebSocket {
@OnOpen
public void on