在当今数字化浪潮下,传统电器零售行业面临着信息更新滞后、订单处理繁琐、库存与销售数据脱节等多重挑战。针对这些痛点,我们设计并实现了一套基于SSM(Spring + Spring MVC + MyBatis)技术栈的电器商品在线销售平台,命名为“智电器销链”。该系统为中小型电器商家提供了一个高效、稳定且易于维护的电商解决方案,实现了从商品上架、库存管理到订单处理的全流程数字化。
系统采用经典的三层架构设计,确保了代码的高内聚和低耦合。Spring框架作为核心容器,通过依赖注入(DI)和控制反转(IoC)机制管理业务对象,有效降低了组件间的依赖性。Spring MVC模块负责Web层的请求调度,清晰分离了前端交互、业务逻辑与数据响应。数据持久层则由MyBatis担当,通过灵活的XML映射文件或注解方式,简化了数据库操作。前端使用JSP进行页面渲染,并结合Ajax技术实现异步数据交互,提升了用户体验。
数据库设计亮点
系统的数据模型设计严谨,共包含13张表,支撑着核心业务逻辑的运转。以下重点分析两张核心表的设计。
商品信息表(product)的设计 体现了对电器商品复杂属性的充分考虑。该表不仅包含基础的商品名称、价格、库存数量,还设计了分类ID(category_id)与品牌ID(brand_id)字段,通过外键关联实现商品的多级分类与品牌管理。特别值得注意的是image_url字段,用于存储商品主图的路径,支持商家上传多张图片展示商品细节。status字段采用枚举类型,标识商品的上架/下架状态,便于进行商品生命周期管理。
CREATE TABLE product (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL COMMENT '商品名称',
category_id int(11) NOT NULL COMMENT '分类ID',
brand_id int(11) NOT NULL COMMENT '品牌ID',
price decimal(10,2) NOT NULL COMMENT '销售价格',
stock int(11) NOT NULL DEFAULT '0' COMMENT '库存数量',
image_url varchar(500) DEFAULT NULL COMMENT '主图URL',
description text COMMENT '商品描述',
status enum('ON_SALE','OFF_SALE') DEFAULT 'ON_SALE' COMMENT '商品状态',
create_time datetime DEFAULT CURRENT_TIMESTAMP,
update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_category_id (category_id),
KEY idx_brand_id (brand_id),
KEY idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品信息表';
订单表(order)的设计 则重点关注了交易数据的完整性与状态追踪。该表包含订单编号(order_no)、用户ID(user_id)、总金额(total_amount)等核心字段。其设计亮点在于status字段,该字段使用枚举类型定义了订单的完整生命周期状态,如PENDING_PAYMENT(待支付)、PAID(已支付)、SHIPPED(已发货)、COMPLETED(已完成)、CANCELLED(已取消)。这种设计使得订单状态的流转清晰可控,为后续的订单查询、统计和业务流程控制提供了坚实基础。payment_time和ship_time等时间戳字段,则精确记录了订单关键操作的时间点。
CREATE TABLE `order` (
id int(11) NOT NULL AUTO_INCREMENT,
order_no varchar(64) NOT NULL COMMENT '订单编号',
user_id int(11) NOT NULL COMMENT '用户ID',
total_amount decimal(10,2) NOT NULL COMMENT '订单总金额',
status enum('PENDING_PAYMENT','PAID','SHIPPED','COMPLETED','CANCELLED') DEFAULT 'PENDING_PAYMENT',
payment_time datetime DEFAULT NULL COMMENT '支付时间',
ship_time datetime DEFAULT NULL COMMENT '发货时间',
create_time datetime DEFAULT CURRENT_TIMESTAMP,
update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_order_no (order_no),
KEY idx_user_id (user_id),
KEY idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
核心功能实现与代码解析
1. 商品管理模块
商品管理是系统的基石,实现了电器的增删改查、上下架及库存预警功能。后端通过ProductController接收前端请求,ProductService封装核心业务逻辑,如库存检查、价格校验等,最后由ProductMapper与数据库交互。
ProductService接口定义了商品管理的核心契约,包括根据ID查询、分页查询、新增和更新商品等方法。
public interface ProductService {
/**
* 根据ID查询商品详情
*/
Product getProductById(Integer id);
/**
* 分页查询商品列表
*/
PageInfo<Product> getProductList(Integer pageNum, Integer pageSize, String keyword, Integer categoryId);
/**
* 新增商品
*/
boolean addProduct(Product product);
/**
* 更新商品信息
*/
boolean updateProduct(Product product);
/**
* 更新商品状态(上架/下架)
*/
boolean updateProductStatus(Integer id, String status);
}
ProductController则提供了对应的RESTful API接口,处理HTTP请求,进行参数校验,并调用服务层方法。
@RestController
@RequestMapping("/api/product")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/{id}")
public ApiResponse<Product> getProduct(@PathVariable Integer id) {
Product product = productService.getProductById(id);
return ApiResponse.success(product);
}
@GetMapping("/list")
public ApiResponse<PageInfo<Product>> getProductList(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) String keyword,
@RequestParam(required = false) Integer categoryId) {
PageInfo<Product> pageInfo = productService.getProductList(pageNum, pageSize, keyword, categoryId);
return ApiResponse.success(pageInfo);
}
}
商品列表管理界面,支持按关键字、分类搜索,并展示库存和状态。
2. 购物车与订单生成
用户将心仪电器加入购物车后,系统会实时计算总价。下单时,OrderService的createOrder方法是核心,它包含了一个事务性操作:校验库存、锁定库存、生成订单、清空购物车项。这种设计确保了在高并发场景下数据的一致性。
@Service
@Transactional
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private ProductMapper productMapper;
@Autowired
private CartMapper cartMapper;
@Override
public Order createOrder(Integer userId, List<Integer> cartItemIds, Address address) {
// 1. 校验购物车商品和库存
List<CartItem> cartItems = cartMapper.selectByIdsAndUserId(cartItemIds, userId);
if (cartItems.isEmpty()) {
throw new BusinessException("购物车商品不存在");
}
for (CartItem item : cartItems) {
Product product = productMapper.selectByPrimaryKey(item.getProductId());
if (product.getStock() < item.getQuantity()) {
throw new BusinessException("商品 [" + product.getName() + "] 库存不足");
}
}
// 2. 计算订单总金额
BigDecimal totalAmount = cartItems.stream()
.map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 3. 生成订单号
String orderNo = generateOrderNo();
// 4. 创建订单主记录
Order order = new Order();
order.setOrderNo(orderNo);
order.setUserId(userId);
order.setTotalAmount(totalAmount);
order.setStatus(OrderStatus.PENDING_PAYMENT);
order.setShippingAddress(address.getDetailAddress());
orderMapper.insert(order);
// 5. 创建订单明细并扣减库存
for (CartItem cartItem : cartItems) {
OrderItem orderItem = new OrderItem();
orderItem.setOrderId(order.getId());
orderItem.setProductId(cartItem.getProductId());
orderItem.setProductName(cartItem.getProductName());
orderItem.setProductImage(cartItem.getProductImage());
orderItem.setQuantity(cartItem.getQuantity());
orderItem.setUnitPrice(cartItem.getPrice());
orderItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(cartItem.getQuantity())));
orderItemMapper.insert(orderItem);
// 扣减库存
productMapper.decreaseStock(cartItem.getProductId(), cartItem.getQuantity());
}
// 6. 清空已下单的购物车项
cartMapper.deleteByIds(cartItemIds);
return order;
}
private String generateOrderNo() {
// 生成规则: 时间戳 + 随机数
return System.currentTimeMillis() + String.valueOf((int)((Math.random() * 9 + 1) * 1000));
}
}
购物车页面,用户可查看选购的商品,修改数量,并一键生成订单。
3. 订单状态管理
订单生成后,其状态会随着业务流程推进而流转。OrderController提供了订单列表查询和状态更新接口。管理员在后台发货后,调用shipOrder接口,更新订单状态为“已发货”并记录发货时间。
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/list")
public ApiResponse<PageInfo<OrderVO>> getOrderList(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) String status) {
PageInfo<OrderVO> pageInfo = orderService.getOrderListByStatus(pageNum, pageSize, status);
return ApiResponse.success(pageInfo);
}
@PostMapping("/{orderId}/ship")
public ApiResponse<Void> shipOrder(@PathVariable Integer orderId) {
boolean success = orderService.shipOrder(orderId);
if (success) {
return ApiResponse.success();
} else {
return ApiResponse.error("发货失败");
}
}
}
对应的服务层方法shipOrder负责具体的状态变更逻辑。
@Override
public boolean shipOrder(Integer orderId) {
Order order = orderMapper.selectByPrimaryKey(orderId);
if (order == null || !OrderStatus.PAID.equals(order.getStatus())) {
return false; // 只有已支付的订单才能发货
}
order.setStatus(OrderStatus.SHIPPED);
order.setShipTime(new Date());
return orderMapper.updateByPrimaryKey(order) > 0;
}
订单管理后台,管理员可查看所有订单,并根据状态进行筛选和操作(如发货)。
4. 数据统计与报表
为帮助商家洞察经营情况,系统提供了简单的数据统计功能。StatisticService中的getSalesData方法,通过MyBatis的动态SQL,可以按日、周、月等维度统计销售额和订单量。
public interface StatisticService {
/**
* 获取销售数据统计
* @param type 统计类型:day, week, month
* @param startDate 开始日期
* @param endDate 结束日期
* @return 统计结果列表
*/
List<SalesDataVO> getSalesData(String type, Date startDate, Date endDate);
}
其Mapper XML文件使用<choose>标签构建动态SQL,以适应不同的统计粒度需求。
<!-- StatisticMapper.xml -->
<mapper namespace="com.electrical.sales.mapper.StatisticMapper">
<select id="selectSalesData" resultType="com.electrical.sales.vo.SalesDataVO">
SELECT
<choose>
<when test="type == 'day'">
DATE(create_time) as datePoint,
</when>
<when test="type == 'week'">
YEARWEEK(create_time) as datePoint,
</when>
<when test="type == 'month'">
DATE_FORMAT(create_time, '%Y-%m') as datePoint,
</when>
</choose>
COUNT(*) as orderCount,
SUM(total_amount) as totalSales
FROM `order`
WHERE status IN ('PAID', 'SHIPPED', 'COMPLETED')
AND create_time BETWEEN #{startDate} AND #{endDate}
GROUP BY datePoint
ORDER BY datePoint
</select>
</mapper>
销售数据统计页面,以图表形式展示不同时间维度的销售额和订单量趋势。
实体模型与业务逻辑
系统的实体模型精确地映射了业务概念。以Order和OrderItem实体为例,它们构成了一对多的关系,清晰地描述了“一个订单包含多个子项”这一核心业务事实。Order实体负责管理订单级别的信息(如总金额、状态、用户),而OrderItem实体则记录了每个具体商品的购买详情(如商品ID、单价、数量)。这种设计不仅符合数据库范式,也使业务代码的逻辑更加清晰。
public class Order {
private Integer id;
private String orderNo;
private Integer userId;
private BigDecimal totalAmount;
private OrderStatus status;
private Date paymentTime;
private Date shipTime;
private String shippingAddress;
private Date createTime;
private Date updateTime;
// 省略getter和setter
}
public class OrderItem {
private Integer id;
private Integer orderId;
private Integer productId;
private String productName;
private String productImage;
private Integer quantity;
private BigDecimal unitPrice;
private BigDecimal totalPrice;
private Date createTime;
// 省略getter和setter
}
业务逻辑层通过服务(Service)类将这些实体模型组织起来,完成复杂的业务操作。例如,订单创建服务不仅操作Order和OrderItem,还会调用ProductService来扣减库存,调用CartService来清理购物车,确保了业务事务的原子性。
功能展望与优化方向
“智电器销链”系统已具备电器在线销售的核心功能,为应对未来更复杂的业务场景和提升系统能力,可以考虑以下优化方向:
引入分布式缓存提升性能:当前系统在高并发读场景下(如商品列表页、商品详情页),数据库压力较大。可以引入Redis作为分布式缓存,将热点商品数据、分类信息缓存起来,显著降低数据库负载,提升响应速度。实现思路是在
ProductService的查询方法中,加入缓存查询逻辑,采用Cache-Aside模式。集成第三方支付与物流跟踪:目前订单流程中的支付和物流环节较为简化。未来可以集成支付宝、微信支付等主流支付渠道,提供更安全便捷的支付体验。同时,对接顺丰、三通一达等物流公司的API,实现下单即生成物流单号,并实时回传物流轨迹,让用户随时查看商品配送状态。
构建智能化推荐引擎:为了提升销售额和用户体验,可以引入基于用户行为的商品推荐功能。通过收集用户的浏览、搜索、购买记录,使用协同过滤或基于内容的推荐算法,在商品详情页、首页等位置展示“猜你喜欢”、“购买了此商品的用户还购买了”等个性化推荐列表。初期可采用基于物品的协同过滤,实现相对简单且效果明显。
实现更细粒度的权限管理系统(RBAC):随着业务发展,商家内部可能有不同角色的员工(如超级管理员、商品编辑员、订单操作员)需要操作系统。可以引入基于角色的访问控制(RBAC)模型,设计用户、角色、权限三张表,实现动态的、可配置的权限管理,确保数据安全和操作合规。
前后端分离与微服务化重构:从长远架构演进看,可以将目前的JSP前后端耦合架构升级为前后端分离模式(如后端提供REST API,前端使用Vue.js/React)。在此基础上,进一步将 monolithic 的单体应用拆分为微服务(如用户服务、商品服务、订单服务、库存服务),每个服务独立部署、扩展,从而提高系统的整体弹性、可维护性和开发效率。
该系统通过严谨的SSM架构设计、合理的数据库建模和清晰的代码实现,为电器零售商的数字化转型提供了强有力的技术支撑。其模块化设计和可扩展性为未来的功能增强和技术演进预留了充足的空间。