传统 SSM 与 Spring Boot 开发对比:从配置地狱到约定优于配置
一、为什么需要对比?
了解 Spring Boot 之前,先看传统 SSM(Spring + Spring MVC + MyBatis)是怎么做的,才能理解 Spring Boot 到底解决了什么问题。
下面以一个最简单的 Web 应用为例:配置一个数据源,写一个 Mapper 查询用户信息,通过 HTTP 接口返回 JSON。
二、传统 SSM 方式(XML 配置时代)
项目结构
src/main/webapp/WEB-INF/
├── web.xml
├── applicationContext.xml
└── spring-mvc.xml
src/main/resources/
└── mybatis-config.xml
src/main/java/
└── com/example/
├── controller/
├── service/
└── mapper/
1. web.xml(配置前端控制器)
xml
<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-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2. applicationContext.xml(配置数据源、MyBatis)
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/test"/>
<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"/>
</bean>
<!-- Mapper 扫描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
3. spring-mvc.xml(配置视图解析器、注解驱动)
xml
<mvc:annotation-driven/>
<context:component-scan base-package="com.example.controller"/>
4. 部署方式
用 Maven 打包成 War,丢到外置 Tomcat 的 webapps 目录下,启动 Tomcat。
5. 配置总结
| 配置文件 | 核心内容 |
|---|---|
web.xml |
DispatcherServlet、ContextLoaderListener |
applicationContext.xml |
DataSource、SqlSessionFactory、事务管理器 |
spring-mvc.xml |
注解驱动、Controller 扫描、视图解析器 |
mybatis-config.xml |
MyBatis 全局配置(可选) |
除了这些,还有:
pom.xml里要手动管理 Spring、MyBatis、数据库驱动、连接池、Jackson 等依赖的版本兼容性。applicationContext.xml和spring-mvc.xml是分层的,Spring 容器和 Spring MVC 容器各有一套配置,初学者很容易搞混父子容器的关系。
三、Spring Boot 方式(同一功能,相同依赖)
项目结构
src/main/java/com/example/
├── Application.java # 启动类
└── controller/
└── UserController.java
src/main/resources/
├── application.yml
└── mapper/
└── UserMapper.xml
pom.xml
1. pom.xml(依赖管理)
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<dependencies>
<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.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
2. application.yml(配置数据源)
yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.entity
3. 启动类
java
@SpringBootApplication
@MapperScan("com.example.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4. Controller
java
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
return userMapper.selectById(id);
}
}
5. 部署方式
mvn clean package 打成 Jar 包,执行 java -jar xxx.jar。
6. 配置总结
| 配置项 | 做了什么 |
|---|---|
pom.xml |
继承 spring-boot-starter-parent,引入 starter-web 和 mybatis-spring-boot-starter |
application.yml |
只写了数据库连接信息和 MyBatis 的 mapper 位置 |
| 启动类 | 加了 @SpringBootApplication 和 @MapperScan |
| 其他 | 没了 |
四、直接对比
| 对比维度 | 传统 SSM | Spring Boot |
|---|---|---|
| 依赖管理 | 手动维护版本号,容易 Jar 包冲突 | 继承 starter-parent,版本由 Starter 统一管理 |
| Spring 配置 | 至少 3 个 XML 文件(web.xml + 两个 Spring 容器配置) | 0 个 XML,只有 application.yml |
| MyBatis 整合 | 手动配置 SqlSessionFactoryBean、MapperScannerConfigurer、DataSourceTransactionManager |
引入 mybatis-spring-boot-starter,在 yml 里写两行配置 |
| Controller 配置 | 需要在 spring-mvc.xml 中配置 <mvc:annotation-driven/> 和包扫描 |
默认就有,@SpringBootApplication 自带组件扫描 |
| Web 容器 | 打 War 包,部署到外置 Tomcat | 打 Jar 包,内嵌 Tomcat,用 java -jar 直接跑 |
| 启动流程 | 配置 Tomcat → 部署 War → 启动 Tomcat | mvn package → java -jar |
| 开发环境差异 | 本地用 IDEA 配置 Tomcat 插件,生产部署到 Linux 上的 Tomcat,容易有环境不一致问题 | 本地和生产都用 java -jar,执行环境完全一致 |
| 配置文件数量 | 4~5 个 XML + 1 个 properties | 1 个 yml + 1 个启动类 |
五、Spring Boot 对 SSM 做了什么减法?
配置简化 :SSM 里需要手动声明的 DataSource、SqlSessionFactory、DispatcherServlet 等 Bean,Spring Boot 通过 @EnableAutoConfiguration 检测到 classpath 里有对应依赖后自动创建。@ConditionalOnClass、@ConditionalOnMissingBean 这些条件注解控制自动配置的生效条件,你写了自定义配置就会覆盖默认的。
依赖版本管理 :spring-boot-starter-parent 的 <dependencyManagement> 里锁定了数百个常用库的版本,你引入 starter-web 时,Spring MVC、Tomcat、Jackson 的版本都已确定,不会冲突。
部署简化 :内嵌 Tomcat 是 spring-boot-starter-web 自带的依赖,SpringApplication.run() 启动时创建 Tomcat 实例并注册 DispatcherServlet。打 Jar 包时所有依赖(包括 Tomcat)都打进一个可执行 Jar 里,java -jar 直接启动,无需外置容器。
六、对比
| 对比点 | SSM 时代 | Spring Boot 时代 |
|---|---|---|
| 配置文件数 | 4 个 XML + 1 个 properties | 1 个 yml + 1 个启动类 |
| 依赖版本管理 | 手动锁定,容易冲突 | 父 POM 统一管理 |
| 部署方式 | 打 War 包,部署到 Tomcat | 打 Jar 包,java -jar 运行 |
| MyBatis 整合 | 手动配置 SqlSessionFactory 等 3~4 个 Bean | 引入 Starter,yml 配数据源即可 |
| 项目启动耗时 | 依赖外置容器启动速度 | 内置容器,启动快 |
就能理解 Spring Boot 的核心价值:不是多了一个新框架,而是把 Spring 生态里那些机械重复的配置工作自动化了。