前言
在Java企业级开发领域,SSM(Spring+SpringMVC+MyBatis)框架组合一直占据着重要地位。这三个轻量级框架各司其职又相互配合,为开发者提供了高效、灵活的开发体验。本文将深入探讨SSM框架的整合过程,揭示整合背后的原理,并提供实际开发中的最佳实践,帮助开发者构建高质量的Java Web应用。
一、SSM框架概述
1.1 为什么选择SSM框架组合?
SSM框架组合在Java Web开发中广受欢迎,主要原因在于:
Spring:提供了全面的IoC(控制反转)和AOP(面向切面编程)功能,是整合的核心
SpringMVC:基于Spring的MVC框架,处理Web层请求和响应
MyBatis:优秀的持久层框架,简化了数据库操作
三者结合形成了清晰的分层架构:
表示层:SpringMVC处理用户交互
业务层:Spring管理业务逻辑和事务
持久层:MyBatis负责数据访问
1.2 SSM与SSH的对比
特性 | SSM | SSH |
---|---|---|
持久层框架 | MyBatis(SQL更灵活) | Hibernate(全自动ORM) |
学习曲线 | 相对平缓 | 较陡峭 |
性能 | 更高(直接控制SQL) | 较好(自动优化) |
适用场景 | 复杂SQL、高性能需求 | 快速开发、标准CRUD |
二、SSM整合详细步骤
2.1 环境准备
<!-- Maven依赖示例 -->
<dependencies>
<!-- Spring核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.18</version>
</dependency>
<!-- SpringMVC -->
<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>
<!-- 数据库相关 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- 其他工具 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.2</version>
</dependency>
</dependencies>
2.2 Spring与SpringMVC整合
2.2.1 web.xml配置
<!-- web.xml核心配置 -->
<web-app>
<!-- 配置SpringMVC前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置Spring上下文监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 指定Spring配置文件位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
</web-app>
2.2.2 父子容器关系
父容器:由ContextLoaderListener创建,加载service、dao等bean
子容器:由DispatcherServlet创建,加载controller等web相关bean
特点:子容器可以访问父容器的bean,但父容器不能访问子容器的bean
2.3 Spring与MyBatis整合
2.3.1 数据源配置
<!-- spring-context.xml中数据源配置 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm_demo?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<!-- 连接池配置 -->
<property name="initialSize" value="5"/>
<property name="maxActive" value="20"/>
<property name="maxWait" value="60000"/>
</bean>
2.3.2 SqlSessionFactory配置
<!-- MyBatis SqlSessionFactory配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 指定MyBatis全局配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 指定mapper.xml文件位置 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<!-- 配置别名包 -->
<property name="typeAliasesPackage" value="com.example.entity"/>
</bean>
2.3.3 Mapper接口扫描
<!-- Mapper接口扫描配置 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
2.4 事务管理配置
<!-- 事务管理器配置 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 注解驱动的事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 事务增强配置(可选) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
三、SSM整合高级技巧
3.1 多数据源配置
@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(
@Qualifier("primaryDataSource") DataSource primaryDataSource,
@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("primary", primaryDataSource);
targetDataSources.put("secondary", secondaryDataSource);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);
dataSource.setDefaultTargetDataSource(primaryDataSource);
return dataSource;
}
}
3.2 MyBatis分页插件集成
<!-- 配置分页插件 -->
<bean id="pageInterceptor" class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<value>
helperDialect=mysql
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
</value>
</property>
</bean>
<!-- 将插件添加到MyBatis -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 其他配置... -->
<property name="plugins">
<array>
<ref bean="pageInterceptor"/>
</array>
</property>
</bean>
3.3 全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(Exception.class)
@ResponseBody
public Result handleException(HttpServletRequest request, Exception e) {
logger.error("请求地址:" + request.getRequestURL(), e);
if (e instanceof BusinessException) {
return Result.error(e.getMessage());
} else if (e instanceof NoHandlerFoundException) {
return Result.error(404, "接口不存在");
} else {
return Result.error("服务异常");
}
}
}
四、SSM整合常见问题与解决方案
4.1 常见问题排查
Bean创建异常
检查包扫描路径是否正确
检查依赖注入是否正确(@Autowired或@Resource)
查看是否有循环依赖
事务不生效
确保方法为public
检查是否在同一个类中调用
确认是否抛出RuntimeException
MyBatis映射问题
检查mapper.xml中namespace是否正确
确认SQL语句是否正确
检查resultMap配置
4.2 性能优化建议
MyBatis一级缓存与二级缓存
合理使用一级缓存(SqlSession级别)
谨慎启用二级缓存(Mapper级别),考虑数据一致性
SQL优化
使用MyBatis的懒加载
避免N+1查询问题
合理使用索引
连接池配置优化
根据并发量调整连接池大小
设置合理的超时时间
定期监控连接池状态
五、从SSM到Spring Boot的演进
虽然SSM组合非常强大,但随着Spring Boot的兴起,开发方式正在发生变化:
特性 | SSM | Spring Boot |
---|---|---|
配置方式 | XML为主 | 约定优于配置,注解为主 |
依赖管理 | 手动管理 | Starter依赖自动管理 |
部署方式 | 需要外部容器 | 内嵌容器,可执行JAR |
开发效率 | 中等 | 高 |
适用场景 | 传统企业项目 | 微服务、快速开发项目 |
对于新项目,推荐考虑Spring Boot + MyBatis组合,它保留了MyBatis的灵活性,同时享受Spring Boot的开发便利。
结语
SSM框架整合是Java Web开发的重要技能,通过本文的学习,相信你已经掌握了SSM整合的核心要点和高级技巧。在实际项目中,要根据业务需求灵活调整配置,并持续关注性能优化。技术不断演进,但分层架构和模块化设计的思想永远不会过时。
思考题:在你的项目中,SSM框架遇到了哪些挑战?是如何解决的?欢迎在评论区分享你的经验!