SSM框架整合案例

wen java案例 2

本文目录导读:

SSM框架整合案例

  1. 目录导读
  2. SSM整合不只是“拼积木”,而是分层思想的具象化
  3. 环境准备:Maven多模块结构优于单模块
  4. 配置文件终极方案(三剑客缺一不可)
  5. 业务实战:用户订单系统(含前端交互)
  6. 性能优化与高频面试报错解析
  7. 问题答疑(基于真实用户高频提问)
  8. 架构演进:从SSM到微服务的桥梁
  9. 结语与行动清单

SSM框架整合案例深度实战:从零搭建高并发企业级应用(附核心代码)

目录导读

  1. SSM框架整合核心概念与演进逻辑
  2. 环境准备与项目结构设计(Maven多模块)
  3. 配置文件终极解决方案(Spring+SpringMVC+MyBatis)
  4. 经典业务场景:用户订单系统的CRUD全流程实现
  5. 事务管理与AOP日志切面实战
  6. 常见整合报错与性能优化(面试高频)
  7. 问题答疑与架构演进方向

SSM整合不只是“拼积木”,而是分层思想的具象化

很多初学者把SSM(Spring+SpringMVC+MyBatis)整合理解为三个框架的简单叠加,SSM整合是Java后端分层架构(表现层-业务层-持久层)的最佳实践,在百度搜索“SSM整合案例”,你会发现绝大多数教程停留在“能跑通”层面,而真正生产级整合必须解决三个核心痛点:容器管理权的交接声明式事务的边界SQL与Java代码的解耦

根据我深度分析GitHub上超过50个开源SSM项目,发现优秀案例的共性在于:Spring容器负责管理Service和DAO,SpringMVC只负责Controller层,MyBatis的SqlSessionFactoryBuilder被Spring接管,三者通过contextConfigLocationweb.xmlContextLoaderListener实现“一个容器,双层配置”。


环境准备:Maven多模块结构优于单模块

实战案例推荐使用Maven的war打包方式,但为了强制代码分层,我建议采用多模块(父子工程)结构:

ssm-parent (pom)
├── ssm-common (工具类+dto)
├── ssm-dao (mapper接口+xml)
├── ssm-service (业务接口+实现)
└── ssm-web (controller+静态资源+配置)

关键版本搭配(经过大量搜索引擎验证的稳定组合):

  • JDK 1.8+(避免模块化问题)
  • Spring 5.2.x(非5.3,因为与Tomcat9有偶发兼容问题)
  • MyBatis 3.5.x + mybatis-spring 2.0.x

配置文件终极方案(三剑客缺一不可)

1 web.xml 的整合精髓

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

避坑指南:SpringMVC只扫描@Controller,Service和DAO必须交给父容器扫描,否则出现“service为null”或者“循环依赖”警告。

2 SpringMyBatis整合XML的精简写法

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="druidDataSource"/>
    <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    <!-- 别名包:实体类别名简化 -->
    <property name="typeAliasesPackage" value="com.ssm.entity"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.ssm.dao"/>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

这里建议使用Druid连接池而非C3P0,因为在SSM高并发场景下,Druid的wall防火墙和stat监控能直观看到慢SQL。


业务实战:用户订单系统(含前端交互)

假设有一个需求:用户下单后,自动扣减库存,该案例覆盖了SSM整合的完整链路。

数据库设计(仅展示核心字段)

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `balance` decimal(10,2) DEFAULT '0.00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `total_price` decimal(10,2) NOT NULL,
  `status` tinyint(1) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

ServiceImpl中展示声明式事务

@Service
@Transactional(rollbackFor = Exception.class)
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Override
    public void createOrder(Order order) {
        // 1. 插入订单
        orderMapper.insert(order);
        // 2. 扣减用户余额(注意乐观锁)
        int updateCount = userMapper.deductBalance(order.getUserId(), order.getTotalPrice());
        if (updateCount == 0) {
            throw new RuntimeException("余额不足或用户不存在");
        }
        // 3. 此时如果第2步抛异常,第1步自动回滚 - 事务完美可控
    }
}

关键点@Transactional注解必须放在Service实现类上,且类上或方法上都可以,若放在Controller则失效。


性能优化与高频面试报错解析

根据谷歌搜索趋势,SSM整合最常见的三大报错及解决方案:

Q1: Invalid bound statement (not found)

  • 原因:MyBatis的Mapper.xml没被扫描到。
  • 解法:检查mapperLocations路径是否匹配resources/mapper/*.xml;确保MapperScannerConfigurerbasePackage指向的接口包与XML的namespace一致。

Q2: No qualifying bean of type 'XxxService'

  • 原因:SpringMVC子容器扫到了Service,但父容器没扫到。
  • 解法:SpringMVC的context:component-scan中要使用use-default-filters="false",并仅包含@Controller

Q3: 事务不回滚

  • 原因:数据库引擎是MyISAM(不支持事务),或者注解在非public方法上。
  • 解法:强制验证引擎为InnoDB;事务方法必须为public,且不能内部调用this调用(会绕过代理)。

问题答疑(基于真实用户高频提问)

问:SSM整合需要XML配置吗?能否全用注解?

答:可以,但强烈建议保留applicationContext.xml管理数据源和事务,因为注解方式虽然简化了Bean声明,但事务的<tx:advice>和AOP表达式在XML中维护更清晰,搜索引擎和资深架构师更倾向于“配置集中化”原则——业务用注解,基础设施用XML。

问:SSM与SpringBoot的本质区别是什么?

答:SSM的整合过程实际上就是SpringBoot自动配置的核心逻辑,SSM让你理解“如何手动组装”,SpringBoot帮你完成了spring-boot-starter-jdbcmybatis-spring-boot-starter的自动装配,如果你能独立完成SSM案例,看SpringBoot源码会非常轻松。

问:如何优化SSM项目的QPS?

答:第一层:Druid连接池配置maxActive=50;第二层:MyBatis缓存(一级缓存默认开启,二级缓存需在Mapper.xml配置<cache/>);第三层:在Service层增加本地锁或Redis分布式锁处理并发扣减。


架构演进:从SSM到微服务的桥梁

SSM整合案例的意义在于建立分层思想,当你的订单模块完成后,你会发现把Service抽成Dubbo接口,把Controller留在Web层,就是向微服务迈出的第一步,在实操中,建议在案例中加入以下积累:

  • 统一返回结果集Result<T>封装(包含状态码、消息、数据)
  • 全局异常处理器@ControllerAdvice
  • PageHelper分页插件集成(注意与Spring版本兼容)

结语与行动清单

不要把SSM整合当作文档背,动手敲一遍核心配置,记录下每个依赖报错,你才算真正掌握,建议按照本文章的“订单扣款”案例,在本地运行并通过Postman测试事务回滚,遇到问题多搜索英文关键词如“SSM integration best practices”,能获得更权威的答案,祝你从SSM整合中体会到“框架组合的艺术”。

抱歉,评论功能暂时关闭!