1. SSM框架技术栈全景解析
SSM(Spring+SpringMVC+MyBatis)作为JavaEE领域经典的开发框架组合,至今仍是企业级应用开发的中坚力量。这套技术栈之所以能经久不衰,关键在于其模块化设计带来的灵活性和扩展性。让我们先拆解这三个核心组件的技术定位:
Spring框架是整个技术栈的基础容器,最新5.3.x版本通过IoC(控制反转)和AOP(面向切面编程)两大核心机制,实现了对象生命周期管理和横切关注点分离。在实际项目中,我们通常会结合注解驱动开发(如@Component、@Service)和JavaConfig配置方式,替代传统的XML配置。特别值得注意的是Spring的声明式事务管理,通过@Transactional注解可以优雅地处理复杂的数据库事务边界。
SpringMVC作为表现层框架,其核心DispatcherServlet采用前端控制器模式,将请求处理流程划分为HandlerMapping、HandlerAdapter、ViewResolver等标准化组件。最新版本对RESTful风格的支持更加完善,@RestController注解使得构建API接口变得异常简单。我在实际开发中发现,合理配置拦截器(Interceptor)和过滤器(Filter)的优先级,能有效处理权限验证、日志记录等横切需求。
MyBatis作为持久层框架,其"半自动化"特性介于Hibernate的全自动ORM和JDBC的手动编码之间。通过XML映射文件或注解方式,开发者可以精细控制SQL语句,同时享受对象关系映射的便利。动态SQL功能(如
技术选型建议:对于需要快速迭代的中小型项目,可以考虑MyBatis-Plus增强工具包;而对复杂事务场景,Spring Data JPA可能是更好的选择。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境搭建与项目初始化实战
2.1 Maven依赖配置精要
创建SSM项目首先需要规范化的依赖管理。以下是最新的核心依赖配置示例(基于Spring 5.3.18和MyBatis 3.5.9):
xml复制<dependencies>
<!-- Spring核心容器 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.18</version>
</dependency>
<!-- Spring MVC支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<!-- MyBatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!-- MyBatis-Spring整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<!-- JDBC连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
</dependencies>
2.2 分层架构配置详解
标准的SSM项目通常采用三层架构设计,对应的配置要点如下:
- 数据源配置(applicationContext-dao.xml):
xml复制<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/ssm_demo?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="initialSize" value="5"/>
<property name="maxActive" value="20"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<property name="typeAliasesPackage" value="com.example.entity"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.dao"/>
</bean>
- 业务层配置(applicationContext-service.xml):
xml复制<context:component-scan base-package="com.example.service"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
- Web层配置(spring-mvc.xml):
xml复制<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
<context:component-scan base-package="com.example.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
常见陷阱:组件扫描路径重叠会导致bean被重复创建,建议controller层和service层使用不同的配置文件分别扫描。
3. 核心机制深度剖析
3.1 Spring IoC容器工作原理
Spring容器的核心是BeanFactory体系,其工作流程可分为以下几个阶段:
- 资源定位:容器通过ResourceLoader加载配置信息(XML/注解/JavaConfig)
- Bean定义解析:将配置转换为BeanDefinition对象
- 依赖注入:
- 构造器注入(循环依赖需特别注意)
- Setter方法注入
- 字段注入(通过@Autowired)
- 初始化回调:
- @PostConstruct注解方法
- InitializingBean接口
- init-method指定方法
三级缓存解决循环依赖的机制值得深入理解:
- 一级缓存(singletonObjects):存放完全初始化好的bean
- 二级缓存(earlySingletonObjects):存放原始bean(尚未填充属性)
- 三级缓存(singletonFactories):存放bean工厂对象
3.2 SpringMVC请求处理流程
一个HTTP请求在SpringMVC中的完整旅程:
- DispatcherServlet接收请求
- HandlerMapping解析请求对应的处理器
- HandlerAdapter适配执行处理器方法
- 参数解析与绑定(@RequestParam、@RequestBody等)
- 拦截器preHandle执行
- 业务方法执行
- 拦截器postHandle执行
- 视图解析与渲染
- 拦截器afterCompletion执行
关键扩展点:
- 自定义参数解析器(实现HandlerMethodArgumentResolver)
- 自定义返回值处理器(实现HandlerMethodReturnValueHandler)
- 异常处理(@ControllerAdvice + @ExceptionHandler)
3.3 MyBatis执行过程解析
SQL语句在MyBatis中的执行轨迹:
- SqlSessionFactoryBuilder解析配置
- SqlSessionTemplate获取SqlSession
- MapperProxy动态代理触发拦截
- Executor执行数据库操作
- SimpleExecutor:简单执行
- ReuseExecutor:重用预处理语句
- BatchExecutor:批量操作
- StatementHandler处理SQL语句
- ParameterHandler处理参数映射
- ResultSetHandler处理结果集
插件开发示例(实现分页功能):
java复制@Intercepts(@Signature(type=StatementHandler.class,
method="prepare",
args={Connection.class,Integer.class}))
public class PaginationInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler handler = (StatementHandler) invocation.getTarget();
// 解析分页参数并重写SQL
return invocation.proceed();
}
}
4. 企业级开发实战技巧
4.1 事务管理最佳实践
Spring声明式事务的传播行为对比:
| 传播行为类型 | 说明 | 适用场景 |
|---|---|---|
| REQUIRED | 支持当前事务,不存在则新建 | 常规数据库操作 |
| REQUIRES_NEW | 新建事务,挂起当前事务 | 日志记录等独立操作 |
| NESTED | 嵌套事务,外层异常回滚内层 | 复杂业务子流程 |
| SUPPORTS | 支持当前事务,不存在则以非事务执行 | 查询操作 |
典型配置示例:
java复制@Service
public class OrderServiceImpl implements OrderService {
@Transactional(propagation=Propagation.REQUIRED,
isolation=Isolation.READ_COMMITTED,
rollbackFor=Exception.class)
public void createOrder(Order order) {
// 主订单处理
orderDao.insert(order);
// 订单明细处理
order.getItems().forEach(item -> {
item.setOrderId(order.getId());
orderItemDao.insert(item);
});
// 库存扣减
inventoryService.reduceStock(order);
}
}
4.2 性能优化方案
- MyBatis二级缓存配置:
xml复制<cache eviction="LRU"
flushInterval="60000"
size="512"
readOnly="true"/>
- 批量操作优化:
java复制public void batchInsert(List<User> users) {
SqlSession session = sqlSessionTemplate.getSqlSessionFactory()
.openSession(ExecutorType.BATCH);
try {
UserMapper mapper = session.getMapper(UserMapper.class);
for (User user : users) {
mapper.insert(user);
}
session.commit();
} finally {
session.close();
}
}
- 连接池调优参数:
| 参数 | 建议值 | 说明 |
|---|---|---|
| initialSize | 5-10 | 初始连接数 |
| maxActive | 20-50 | 最大活跃连接数 |
| minIdle | 5-10 | 最小空闲连接 |
| maxWait | 60000 | 获取连接超时时间(ms) |
| timeBetweenEvictionRunsMillis | 60000 | 检测间隔(ms) |
4.3 安全防护策略
- SQL注入防护:
- 始终使用#{}占位符而非${}拼接SQL
- 对like查询特殊处理:
xml复制<select id="search" resultType="User">
SELECT * FROM user
WHERE name LIKE CONCAT('%', #{keyword}, '%')
</select>
- XSS防御方案:
- 前端:使用vue/react等框架的插值表达式
- 后端:实现Filter对请求参数过滤
- 持久层:入库前进行HTML转义
- CSRF防护配置:
xml复制<bean id="csrfFilter" class="org.springframework.security.web.csrf.CsrfFilter">
<constructor-arg>
<bean class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository"/>
</constructor-arg>
</bean>
5. 常见问题排查手册
5.1 典型异常解决方案
- NoSuchBeanDefinitionException:
- 检查组件扫描路径是否包含目标类
- 确认bean的依赖是否已正确注入
- 查看是否存在多个同类型bean未指定@Qualifier
- Transaction rolled back because it has been marked as rollback-only:
- 检查内层方法是否使用了REQUIRES_NEW传播行为
- 避免在catch块中继续抛出异常
- 使用TransactionTemplate手动控制事务边界
- BindingException: Parameter 'xxx' not found:
- 确认@Param注解在接口方法中正确使用
- 检查XML中的参数名是否与方法参数一致
- 对于Map参数,确保包含所有必需的key
5.2 日志排查技巧
- 开启MyBatis完整日志:
properties复制logging.level.org.mybatis=DEBUG
logging.level.java.sql.Connection=DEBUG
logging.level.java.sql.Statement=DEBUG
- Spring事务日志分析:
properties复制logging.level.org.springframework.transaction=TRACE
logging.level.org.springframework.jdbc=DEBUG
- 请求追踪日志配置:
java复制public class RequestLogFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
long start = System.currentTimeMillis();
chain.doFilter(request, response);
long cost = System.currentTimeMillis() - start;
log.info("Request {} cost {}ms",
((HttpServletRequest)request).getRequestURI(), cost);
}
}
6. 现代化演进路线
6.1 Spring Boot整合方案
传统SSM向Spring Boot迁移的关键步骤:
- 替换pom.xml为starter依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
- 简化配置(application.yml):
yaml复制mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.entity
spring:
datasource:
url: jdbc:mysql://localhost:3306/ssm_demo
username: root
password: 123456
druid:
initial-size: 5
max-active: 20
- 自动配置类示例:
java复制@MapperScan("com.example.dao")
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
6.2 微服务架构适配
SSM在微服务体系中的改造方向:
- 服务注册与发现:
- 集成Nacos/Zookeeper
- 使用Spring Cloud OpenFeign声明式调用
- 分布式事务解决方案:
- Seata AT模式
- 基于消息队列的最终一致性
- 配置中心集成:
java复制@RefreshScope
@RestController
public class ConfigController {
@Value("${custom.config}")
private String config;
}
6.3 响应式编程探索
Reactive与SSM的混合编程模式:
- WebFlux整合MyBatis:
java复制@RestController
public class UserController {
@GetMapping("/users/{id}")
public Mono<User> getUser(@PathVariable Long id) {
return Mono.fromCallable(() -> userDao.selectById(id))
.subscribeOn(Schedulers.boundedElastic());
}
}
- R2DBC异步驱动:
properties复制spring.r2dbc.url=r2dbc:mysql://localhost:3306/test
spring.r2dbc.username=root
spring.r2dbc.password=123456
在实际项目升级过程中,建议采用渐进式改造策略,先从非核心模块试点,逐步积累经验后再全面推广。对于历史悠久的SSM项目,保持架构的稳定性和可维护性往往比追求技术新颖性更重要。
