SSM 框架深度整合实战:从零构建企业级 Java 应用
一、SSM 框架全景解析
SSM 框架是 Java 企业级开发的主流技术栈,由三大核心组件构成:
- Spring:轻量级 IoC 容器和 AOP 框架,用于管理组件生命周期和实现切面编程。
- Spring MVC:基于 MVC 模式的 Web 框架,负责处理 Web 层请求与响应。
- MyBatis:优秀的持久层 ORM 框架,简化数据库操作并实现对象关系映射。
二、Spring 核心特性与应用
2.1 IoC 控制反转
传统对象创建方式需手动实例化:
// 传统对象创建
UserService userService = new UserServiceImpl();
Spring 通过 IoC 容器自动管理对象依赖,使用注解实现依赖注入:
// Spring IoC方式
@Autowired
private UserService userService; // 容器自动注入
2.2 AOP 面向切面编程
利用 AOP 实现声明式事务管理,通过 XML 配置事务切面:
<!-- 声明式事务管理 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="save*" propagation="REQUIRED"/></tx:attributes>
</tx:advice><aop:config><aop:pointcut id="serviceMethods" expression="execution(* com.example.service.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
2.3 注解驱动开发
基于 Java 配置类(@Configuration)替代 XML 配置,简化 Spring 容器配置:
@Configuration
@ComponentScan("com.example")
@EnableTransactionManagement
public class AppConfig {@Beanpublic DataSource dataSource() {// 配置数据源return new DruidDataSource();}
}
三、Spring MVC 工作流程
3.1 请求处理流程
- 用户发送请求至 DispatcherServlet(前端控制器)。
- 处理器映射器(HandlerMapping)根据请求路径匹配目标控制器。
- 控制器调用业务逻辑处理请求,返回 ModelAndView 对象。
- 视图解析器(ViewResolver)将逻辑视图渲染为具体页面。
- 响应结果返回给用户。
3.2 控制器示例
使用 @Controller 和 @RequestMapping 注解定义 Web 控制器,处理 RESTful 请求:
@Controller
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;// GET请求:查询用户详情(返回视图)@GetMapping("/{id}")public String getUser(@PathVariable("id") int id, Model model) {User user = userService.getUserById(id);model.addAttribute("user", user);return "userDetail"; // 对应/WEB-INF/views/userDetail.jsp}// POST请求:新增用户(返回JSON)@PostMapping("/add")@ResponseBodypublic Result addUser(@RequestBody User user) {userService.addUser(user);return Result.success("用户新增成功");}
}
四、MyBatis 高效持久层
4.1 基础配置
在 mybatis-config.xml 中开启驼峰命名映射,自动匹配数据库下划线字段与 Java 驼峰属性:
<!-- mybatis-config.xml -->
<configuration><settings><setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 开启驼峰命名 --></settings>
</configuration>
4.2 Mapper 接口与 XML 映射
注解方式:简单 SQL 直接通过注解编写(如 @Select、@Insert):
// UserMapper.java
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User getUserById(int id);@Insert("INSERT INTO users(name, age) VALUES(#{name}, #{age})")@Options(useGeneratedKeys = true, keyProperty = "id") // 获取自增主键int insertUser(User user);
}
XML 方式:复杂查询使用 XML 配置,支持动态 SQL(如条件查询):
<!-- 复杂查询使用XML -->
<mapper namespace="com.example.mapper.UserMapper"><select id="getUsersByCondition" resultType="User">SELECT * FROM users<where><if test="name != null">name LIKE CONCAT('%', #{name}, '%')</if><if test="minAge != null">AND age >= #{minAge}</if></where></select>
</mapper>
五、SSM 整合全流程
5.1 Maven 依赖配置
在 pom.xml 中引入 Spring、Spring MVC、MyBatis 及整合依赖:
<!-- pom.xml -->
<dependencies><!-- Spring核心 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.20</version></dependency><!-- Spring MVC --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.20</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><!-- 数据库连接池(如Druid) --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency>
</dependencies>
5.2 Spring 整合 MyBatis
通过 applicationContext.xml 配置数据源、SqlSessionFactory 及 Mapper 扫描:
<!-- applicationContext.xml -->
<!-- 数据源配置 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/ssm_demo?useUnicode=true&characterEncoding=utf8"/><property name="username" value="root"/><property name="password" value="123456"/>
</bean><!-- SqlSessionFactory配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="configLocation" value="classpath:mybatis-config.xml"/><property name="mapperLocations" value="classpath:mapper/*.xml"/> <!-- Mapper XML路径 -->
</bean><!-- Mapper接口自动扫描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.example.mapper"/> <!-- Mapper接口包路径 -->
</bean>
5.3 Spring MVC 配置
通过 Java 配置类(WebConfig)替代 XML 配置,定义视图解析器和静态资源处理:
// WebConfig.java
@Configuration
@EnableWebMvc // 启用Spring MVC
@ComponentScan("com.example.controller") // 扫描控制器
public class WebConfig implements WebMvcConfigurer {// 视图解析器:配置JSP视图路径@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/");resolver.setSuffix(".jsp");return resolver;}// 静态资源处理:映射/static/路径到类路径下的static目录@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");}
}
六、SSM 常见问题解决方案
6.1 事务管理失效
原因分析:
- 被 @Transactional 修饰的方法非 public。
- 未捕获 Checked 异常(默认仅回滚 RuntimeException)。
解决方案:
@Transactional(rollbackFor = Exception.class) // 强制回滚所有异常
public void saveUser(User user) throws Exception {// 业务逻辑if (user.getAge() < 18) {throw new Exception("用户年龄未满18岁"); // 触发事务回滚}userMapper.insertUser(user);
}
6.2 MyBatis 查询结果映射失败
排查步骤:
- 检查数据库字段与 POJO 属性是否一致(区分大小写)。
- 若字段名与属性名不匹配,使用 ResultMap 自定义映射:
<resultMap id="userMap" type="User"><id property="id" column="user_id"/> <!-- 主键映射 --><result property="userName" column="user_name"/> <!-- 普通字段映射 -->
</resultMap><select id="getUserById" resultMap="userMap">SELECT user_id, user_name FROM users WHERE user_id = #{id}
</select>
6.3 中文乱码问题
在 web.xml 中配置 CharacterEncodingFilter,强制请求 / 响应使用 UTF-8 编码:
<!-- web.xml -->
<filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param>
</filter>
<filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern> <!-- 对所有请求生效 -->
</filter-mapping>
七、SSM 性能优化策略
7.1 MyBatis 批量操作
使用 ExecutorType.BATCH 执行批量插入,减少数据库交互次数:
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);for (int i = 0; i < 1000; i++) {User user = new User("user_" + i, 20 + i);mapper.insertUser(user);if (i % 200 == 0) { // 每200条提交一次,避免内存溢出sqlSession.flushStatements();}}sqlSession.commit(); // 最终提交事务
}
7.2 连接池配置优化
以 Druid 为例,合理配置连接池参数提升数据库连接效率:
# druid.properties
druid.maxActive=20 # 最大活跃连接数
druid.initialSize=5 # 初始连接数
druid.minIdle=5 # 最小空闲连接数
druid.maxWait=60000 # 获取连接最大等待时间(毫秒)
druid.timeBetweenEvictionRunsMillis=60000 # 空闲连接检测间隔
druid.minEvictableIdleTimeMillis=300000 # 最小存活时间(毫秒)
7.3 二级缓存启用
在 MyBatis 中开启二级缓存,缓存常用查询结果:
<!-- mybatis-config.xml -->
<settings><setting name="cacheEnabled" value="true"/> <!-- 全局开启缓存 -->
</settings><!-- Mapper.xml中配置具体缓存策略 -->
<mapper namespace="com.example.mapper.UserMapper"><cache eviction="LRU" <!-- 缓存淘汰策略:最近最少使用 -->flushInterval="60000" <!-- 自动刷新间隔(毫秒) -->size="1024" <!-- 最大缓存对象数 -->readOnly="true"/> <!-- 只读模式(适用于不可变对象) --><select id="getUserById" resultType="User" useCache="true">SELECT * FROM users WHERE id = #{id}</select>
</mapper>
八、SSM 进阶扩展
8.1 整合 Swagger 生成 API 文档
引入 Swagger 依赖并配置,自动生成 RESTful 接口文档:
<!-- pom.xml -->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version>
</dependency>
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version>
</dependency>
// SwaggerConfig.java
@Configuration
@EnableSwagger2
public class SwaggerConfig {@Beanpublic Docket api() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(new ApiInfoBuilder().title("SSM Demo API").description("企业级Java应用接口文档").version("1.0").build()).select().apis(RequestHandlerSelectors.basePackage("com.example.controller")) // 扫描控制器包.paths(PathSelectors.any()) // 匹配所有路径.build();}
}
访问http://localhost:8080/swagger-ui.html
查看交互式文档。
8.2 使用 Spring Boot 简化配置
通过 Spring Boot 快速搭建 SSM 项目,自动配置依赖和环境:
@SpringBootApplication
@MapperScan("com.example.mapper") // 扫描Mapper接口
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
在 application.properties 中配置数据源和 MyBatis:
# 数据源配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm_demo?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource# MyBatis配置
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.configuration.map-underscore-to-camel-case=true
九、SSM 项目最佳实践
9.1 分层架构设计
采用经典三层架构,明确职责分离:
- Controller 层:处理 Web 请求,调用 Service 层,返回视图或 JSON。
- Service 层:实现业务逻辑,调用 Mapper 层,添加事务控制。
- Mapper 层:操作数据库,封装 SQL 语句,返回 POJO 对象。
- Model 层:定义数据实体类,对应数据库表结构。
9.2 统一异常处理
通过 @ControllerAdvice 全局捕获异常,统一返回标准错误格式:
@ControllerAdvice
@ResponseBody // 直接返回JSON响应
public class GlobalExceptionHandler {// 捕获所有Exception异常@ExceptionHandler(Exception.class)public Result handleException(Exception e) {log.error("系统异常:{}", e.getMessage(), e);return Result.error(500, "服务器内部错误", e.getMessage());}// 自定义业务异常处理@ExceptionHandler(BusinessException.class)public Result handleBusinessException(BusinessException e) {return Result.error(e.getCode(), e.getMessage());}
}// 自定义业务异常类
public class BusinessException extends RuntimeException {private int code; // 错误码public BusinessException(int code, String message) {super(message);this.code = code;}// getters...
}
9.3 日志规范
使用 SLF4J 和 Logback 实现统一日志管理,在 Service 层记录关键操作:
@Service
@Slf4j // 使用Lombok注解自动生成日志对象
public class UserServiceImpl implements UserService {@Overridepublic User getUserById(int id) {log.debug("开始查询用户ID:{}", id); // 调试日志User user = userMapper.getUserById(id);if (user == null) {log.warn("用户ID {} 不存在", id); // 警告日志}log.info("查询用户成功:{}", user); // 信息日志return user;}
}
结语
SSM 框架凭借其成熟的生态和灵活的扩展性,仍是企业级 Java 开发的核心技术栈。掌握 SSM 需重点关注:
-
理解核心原理:IoC/AOP、MVC流程、ORM映射
-
熟练整合配置:XML与注解两种配置方式
-
遵循最佳实践:分层开发、统一异常处理
-
持续性能优化:SQL优化、缓存策略