基于SSM框架的在线女装商城系统 - 源码深度解析

JavaJavaScriptMavenHTMLCSSSSM框架MySQL
2026-03-093 浏览

文章摘要

本系统是一款基于SSM(Spring + Spring MVC + MyBatis)框架构建的在线女装商城平台,旨在为女性消费者提供便捷、安全的一站式服装购物体验。系统核心解决了传统实体店购物受限于时间与空间、商品信息不透明以及选购效率低下的痛点,通过数字化的商品展示、分类检索和在线交易流程,显著降...

随着电子商务的蓬勃发展,传统零售业正经历着深刻的数字化转型。特别是在时尚零售领域,女性消费者对购物体验的便捷性、商品信息的透明度以及个性化服务的需求日益增长。本文详细介绍了一个基于SSM(Spring + Spring MVC + MyBatis)技术栈构建的线上女装零售平台——“风尚衣橱”的设计与实现。该系统旨在通过现代化的Web技术,为中小型女装品牌商和消费者搭建一个高效、稳定、易用的在线交易环境。

系统架构与技术栈

“风尚衣橱”系统采用经典的三层架构模式,将应用逻辑清晰地划分为表现层、业务逻辑层和数据持久层。

表现层由Spring MVC框架负责,它通过DispatcherServlet作为前端控制器,统一接收所有HTTP请求。Controller层处理用户交互逻辑,进行参数绑定、数据验证,并选择合适的视图渲染结果。该层还负责管理用户会话状态,例如购物车数据和登录状态。

业务逻辑层基于Spring框架的核心IoC(控制反转)容器实现。通过依赖注入(DI)机制,系统各个组件之间的耦合度被显著降低。Spring的AOP(面向切面编程)能力被用于处理横切关注点,例如声明式事务管理、系统日志记录和安全性检查,确保了业务代码的纯粹性和可维护性。

数据持久层选用MyBatis框架,它通过XML配置或注解的方式,将Java对象(POJOs)与数据库表中的记录进行灵活的映射(ORM)。MyBatis强大的动态SQL功能使得构建复杂的商品查询条件(如多条件筛选、模糊搜索)变得高效而简洁。

项目采用Maven进行依赖管理和构建,确保了第三方库版本的一致性和项目结构的标准化。前端页面使用HTML、CSS和JavaScript开发,实现了响应式布局,以适配不同尺寸的终端设备。数据库系统选用MySQL,以其稳定性和高性能满足电商系统的数据存储需求。

核心数据库设计剖析

数据库设计是电商系统的基石,直接影响到系统的性能、数据一致性和扩展性。“风尚衣橱”的数据库设计遵循第三范式,减少了数据冗余,并通过合理的主外键关系确保了数据的完整性。以下重点分析两个核心表的设计。

1. 商品表(product)设计

商品表是系统的核心数据载体,其设计需要兼顾商品描述的丰富性和查询性能。

CREATE TABLE `product` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品ID',
  `name` varchar(255) NOT NULL COMMENT '商品名称',
  `description` text COMMENT '商品描述',
  `price` decimal(10,2) NOT NULL COMMENT '商品价格',
  `stock` int(11) NOT NULL COMMENT '商品库存',
  `category_id` int(11) DEFAULT NULL COMMENT '分类ID',
  `image_url` varchar(500) DEFAULT NULL COMMENT '商品主图URL',
  `status` int(11) DEFAULT '1' COMMENT '商品状态(1:上架,0:下架)',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_category_id` (`category_id`),
  KEY `idx_status` (`status`),
  KEY `idx_create_time` (`create_time`),
  CONSTRAINT `fk_product_category` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

设计亮点分析:

  • 字段类型优化price字段使用DECIMAL(10,2)类型,精确存储货币金额,避免浮点数精度问题。stock库存字段使用整型,便于原子性操作。
  • 索引策略:除了主键索引,还为category_id(分类查询)、status(上下架状态过滤)和create_time(按新品排序)建立了索引。这种复合索引策略极大地提升了商品列表页的查询速度,特别是在多条件筛选和排序场景下。
  • 外键约束:通过FOREIGN KEY约束与分类表(category)关联,确保了数据的一致性。当某个分类被删除时,相关商品的category_id会被设置为NULLON DELETE SET NULL),而不是级联删除商品,这是一种更安全的业务逻辑处理方式。
  • 审计字段create_timeupdate_time字段自动记录数据的生命周期,便于后续的数据分析和监控。

2. 订单表(order)与订单项表(order_item)设计

电商系统中的订单模型通常采用主表-子表的结构来设计,以应对一个订单包含多个商品的情况。

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单ID',
  `order_no` varchar(64) NOT NULL COMMENT '订单号',
  `user_id` int(11) NOT NULL COMMENT '用户ID',
  `total_amount` decimal(10,2) NOT NULL COMMENT '订单总金额',
  `status` int(11) NOT NULL COMMENT '订单状态',
  `payment_time` datetime DEFAULT NULL COMMENT '支付时间',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_order_no` (`order_no`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

CREATE TABLE `order_item` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单项ID',
  `order_id` int(11) NOT NULL COMMENT '订单ID',
  `product_id` int(11) NOT NULL COMMENT '商品ID',
  `product_name` varchar(255) NOT NULL COMMENT '商品名称(快照)',
  `product_price` decimal(10,2) NOT NULL COMMENT '商品单价(快照)',
  `quantity` int(11) NOT NULL COMMENT '购买数量',
  `total_price` decimal(10,2) NOT NULL COMMENT '订单项总价',
  PRIMARY KEY (`id`),
  KEY `idx_order_id` (`order_id`),
  KEY `idx_product_id` (`product_id`),
  CONSTRAINT `fk_order_item_order` FOREIGN KEY (`order_id`) REFERENCES `order` (`id`) ON DELETE CASCADE,
  CONSTRAINT `fk_order_item_product` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单项表';

设计亮点分析:

  • 订单号唯一性:订单主表使用order_no字段并建立唯一索引(uk_order_no),该订单号通常由系统按规则生成(如时间戳+随机数),用于对外展示和交互,避免了自增主键ID暴露带来的安全隐患。
  • 数据快照:在订单项表(order_item)中,存储了下单时刻的商品名称(product_name)和单价(product_price)。这是电商系统一个至关重要的设计。即使后续商家修改了商品信息或价格,已生成订单的历史数据也不会改变,保证了交易记录的客观性和不可篡改性。
  • 数据一致性:订单总金额(order.total_amount)理论上应等于其下所有订单项总价(order_item.total_price)之和。这一致性通常在业务逻辑层通过事务来保证。在创建订单时,系统会先计算各个订单项金额,再汇总写入订单主表,整个操作在一个数据库事务内完成。

核心功能模块深度解析

1. 商品浏览与多维度筛选

商品展示是电商平台的流量入口。“风尚衣橱”实现了高效的商品分类浏览和灵活的多条件搜索功能。

前端界面展示商品分类浏览 用户可以通过左侧的分类导航栏快速定位到感兴趣的服装品类,页面采用瀑布流或网格布局展示商品图片、名称和价格,视觉体验良好。

后端Controller层核心代码ProductController负责处理商品列表的查询请求。

@Controller
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private ProductService productService;

    @RequestMapping("/list")
    public String listProducts(
            @RequestParam(value = "categoryId", required = false) Integer categoryId,
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam(value = "minPrice", required = false) BigDecimal minPrice,
            @RequestParam(value = "maxPrice", required = false) BigDecimal maxPrice,
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "12") Integer pageSize,
            Model model) {

        // 构建查询条件对象
        ProductQuery query = new ProductQuery();
        query.setCategoryId(categoryId);
        query.setKeyword(keyword);
        query.setMinPrice(minPrice);
        query.setMaxPrice(maxPrice);
        query.setStatus(1); // 只查询上架商品

        // 调用服务层分页查询
        PageInfo<Product> pageInfo = productService.getProductList(query, pageNum, pageSize);

        // 将数据添加到模型,供视图层渲染
        model.addAttribute("pageInfo", pageInfo);
        model.addAttribute("query", query);

        return "product/list";
    }
}

Service层与MyBatis动态SQL: 业务逻辑层封装了复杂的查询逻辑,数据层则利用MyBatis的动态SQL能力组装查询条件。

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Override
    public PageInfo<Product> getProductList(ProductQuery query, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize); // 使用PageHelper实现物理分页
        List<Product> productList = productMapper.selectByQuery(query);
        return new PageInfo<>(productList);
    }
}
<!-- ProductMapper.xml 中的动态SQL语句 -->
<select id="selectByQuery" parameterType="com.maancode.mall.query.ProductQuery" resultMap="BaseResultMap">
    SELECT
    <include refid="Base_Column_List"/>
    FROM product
    WHERE status = 1
    <if test="categoryId != null">
        AND category_id = #{categoryId}
    </if>
    <if test="keyword != null and keyword != ''">
        AND (name LIKE CONCAT('%', #{keyword}, '%') OR description LIKE CONCAT('%', #{keyword}, '%'))
    </if>
    <if test="minPrice != null">
        AND price >= #{minPrice}
    </if>
    <if test="maxPrice != null">
        AND price &lt;= #{maxPrice}
    </if>
    ORDER BY create_time DESC
</select>

此实现通过<if>标签动态拼接SQL条件,避免了编写多个相似查询方法的冗余,提升了代码的复用性和可维护性。PageHelper插件的使用则简化了分页逻辑的实现。

2. 购物车管理与订单生成

购物车是连接商品浏览和订单生成的关键模块,其核心在于管理用户的临时购买意向。

前端界面展示加入购物车 用户在商品详情页选择尺码、颜色和数量后,可一键将商品加入购物车。购物车页面会清晰展示已选商品列表、单价、数量和小计。

购物车Service层核心代码: 购物车业务涉及复杂的逻辑,如验证库存、合并同一商品等。

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private CartItemMapper cartItemMapper;
    @Autowired
    private ProductMapper productMapper;

    @Override
    @Transactional // 声明式事务管理
    public void addToCart(Integer userId, Integer productId, Integer quantity) {
        // 1. 校验商品是否存在且已上架
        Product product = productMapper.selectByPrimaryKey(productId);
        if (product == null || product.getStatus() != 1) {
            throw new RuntimeException("商品不存在或已下架");
        }

        // 2. 校验库存是否充足
        if (product.getStock() < quantity) {
            throw new RuntimeException("商品库存不足");
        }

        // 3. 查询用户购物车中是否已有该商品
        CartItem existItem = cartItemMapper.selectByUserIdAndProductId(userId, productId);
        if (existItem != null) {
            // 如果存在,则更新数量
            existItem.setQuantity(existItem.getQuantity() + quantity);
            cartItemMapper.updateByPrimaryKeySelective(existItem);
        } else {
            // 如果不存在,则新增一条记录
            CartItem newItem = new CartItem();
            newItem.setUserId(userId);
            newItem.setProductId(productId);
            newItem.setQuantity(quantity);
            cartItemMapper.insertSelective(newItem);
        }
    }

    @Override
    @Transactional
    public Order createOrderFromCart(Integer userId, List<Integer> cartItemIds, Address address) {
        // 1. 查询选中的购物车项
        List<CartItem> selectedItems = cartItemMapper.selectByIdsAndUserId(cartItemIds, userId);
        if (selectedItems.isEmpty()) {
            throw new RuntimeException("购物车为空");
        }

        // 2. 创建订单主表记录
        Order order = new Order();
        order.setOrderNo(generateOrderNo()); // 生成唯一订单号
        order.setUserId(userId);
        order.setStatus(OrderStatusEnum.WAIT_PAY.getCode());
        // ... 设置收货地址等信息
        orderMapper.insertSelective(order);

        BigDecimal totalAmount = BigDecimal.ZERO;
        List<OrderItem> orderItems = new ArrayList<>();

        // 3. 遍历购物车项,生成订单项
        for (CartItem cartItem : selectedItems) {
            Product product = productMapper.selectByPrimaryKey(cartItem.getProductId());

            // 再次校验库存
            if (product.getStock() < cartItem.getQuantity()) {
                throw new RuntimeException("商品【" + product.getName() + "】库存不足");
            }

            // 扣减库存(乐观锁)
            int updateCount = productMapper.reduceStock(product.getId(), cartItem.getQuantity());
            if (updateCount == 0) {
                throw new RuntimeException("商品【" + product.getName() + "】库存更新失败,请重试");
            }

            // 构建订单项(数据快照)
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(order.getId());
            orderItem.setProductId(product.getId());
            orderItem.setProductName(product.getName()); // 快照
            orderItem.setProductPrice(product.getPrice()); // 快照
            orderItem.setQuantity(cartItem.getQuantity());
            orderItem.setTotalPrice(product.getPrice().multiply(new BigDecimal(cartItem.getQuantity())));
            orderItemMapper.insertSelective(orderItem);

            orderItems.add(orderItem);
            totalAmount = totalAmount.add(orderItem.getTotalPrice());

            // 从购物车中删除已下单项
            cartItemMapper.deleteByPrimaryKey(cartItem.getId());
        }

        // 4. 更新订单总金额
        order.setTotalAmount(totalAmount);
        orderMapper.updateByPrimaryKeySelective(order);

        return order;
    }

    private String generateOrderNo() {
        // 示例:时间戳 + 随机数
        return System.currentTimeMillis() + "" + (int)((Math.random() * 9 + 1) * 1000);
    }
}

订单确认界面确认订单 在确认订单页面,用户最终核对商品信息、收货地址和总金额,完成支付。

3. 后台商品与订单管理

后台管理系统是平台运营的指挥中心,管理员需要高效的工具来管理商品和订单。

商品管理界面商品管理 管理员可以在此页面进行商品的增、删、改、查、上架/下架等操作。界面通常提供批量操作功能,提升管理效率。

订单管理界面订单管理 管理员可以查看所有订单,并根据订单状态(待付款、待发货、已发货、已完成等)进行筛选和操作,如发货、备注、取消订单等。

后台商品管理的Controller代码示例

@Controller
@RequestMapping("/admin/product")
public class AdminProductController {

    @Autowired
    private ProductService productService;

    @PostMapping("/saveOrUpdate")
    @ResponseBody
    public ResponseEntity<?> saveOrUpdateProduct(@RequestBody @Valid Product product, BindingResult result) {
        if (result.hasErrors()) {
            // 处理参数校验错误
            return ResponseEntity.badRequest().body("参数校验失败");
        }

        try {
            if (product.getId() == null) {
                productService.addProduct(product);
            } else {
                productService.updateProduct(product);
            }
            return ResponseEntity.ok().body("操作成功");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("操作失败: " + e.getMessage());
        }
    }

    @PostMapping("/updateStatus")
    @ResponseBody
    public ResponseEntity<?> updateProductStatus(@RequestParam Integer productId, @RequestParam Integer status) {
        try {
            productService.updateProductStatus(productId, status);
            return ResponseEntity.ok().body("状态更新成功");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("状态更新失败");
        }
    }
}

实体模型与业务逻辑

系统通过一系列精心设计的Java实体类(如User, Product, Category, Order, OrderItem, CartItem)来映射数据库表结构,并承载业务逻辑。这些实体类不仅是数据容器,某些核心业务逻辑也以方法的形式封装在实体类中,遵循了面向对象的设计原则。

例如,在Order实体中,可以封装状态流转的逻辑:

public class Order {
    //
本文关键词
SSM框架在线女装商城系统架构数据库设计源码解析

上下篇

上一篇
没有更多文章
下一篇
没有更多文章