1. 项目背景与改造动机
去年接手维护一个历史遗留的Java Web项目时,发现这个使用传统Maven构建的系统存在几个明显痛点:首先是项目启动需要依赖外置Tomcat容器,每次部署都要经历打包war、上传服务器、配置容器的繁琐流程;其次是依赖管理混乱,pom.xml里充斥着版本冲突的jar包;最头疼的是缺乏健康检查等生产级功能,每次排查问题都像开盲盒。
这让我下定决心将其改造为SpringBoot项目。SpringBoot的嵌入式容器特性可以直接打包成可执行jar,依赖starter的版本仲裁机制能有效解决冲突,而actuator模块提供的监控端点更是运维利器。下面分享从零开始的完整改造过程,包含20+个关键操作步骤和5个典型避坑场景。
2. 环境准备与基础改造
2.1 开发环境配置
工欲善其事必先利其器,建议使用以下环境组合:
- JDK 17(LTS版本,注意与原有项目JDK版本兼容)
- Maven 3.8.6+(配置阿里云镜像加速依赖下载)
- IntelliJ IDEA 2023.2(社区版已足够)
重要提示:必须确保环境变量JAVA_HOME指向正确的JDK路径,这是后续所有操作的基础。遇到过同事因为配置了多个JDK导致编译异常,可以用
mvn -v验证环境。
2.2 项目结构重构
原有Maven项目典型结构:
legacy-project ├── src │ ├── main │ │ ├── java │ │ └── webapp │ │ └── WEB-INF │ └── test └── pom.xml改造后的SpringBoot标准结构:
modern-project ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── example │ │ │ └── Application.java │ │ └── resources │ │ ├── static │ │ ├── templates │ │ └── application.yml │ └── test └── pom.xml关键操作步骤:
- 在IDEA中右键项目 -> Add Framework Support -> 勾选Spring Boot
- 移动webapp下的静态资源到src/main/resources/static
- 将JSP文件迁移到resources/templates(需引入thymeleaf依赖)
- 删除WEB-INF/web.xml(SpringBoot默认使用Servlet 3.0+注解配置)
3. 依赖管理与POM改造
3.1 父POM配置
在原有pom.xml基础上增加spring-boot-starter-parent继承:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.5</version> <relativePath/> </parent>3.2 依赖项优化
典型改造案例对比:
| 原依赖项 | 替换方案 | 作用说明 |
|---|---|---|
| spring-webmvc 4.3.18 | spring-boot-starter-web | 自动包含Tomcat和Jackson |
| log4j 1.2.17 | spring-boot-starter-logging | 默认使用Logback |
| hibernate-core 5.2.12 | spring-boot-starter-data-jpa | 自动配置Hibernate 6.x |
| commons-dbcp 1.4 | spring-boot-starter-jdbc | 提供HikariCP连接池 |
3.3 插件配置
必须添加的maven插件:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>踩坑记录:遇到过Lombok在打包时被包含导致运行异常的情况,通过exclude配置解决。另外建议添加maven-compiler-plugin显式指定Java版本。
4. 核心代码适配
4.1 启动类创建
在根包下创建Application.java:
@SpringBootApplication public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }注意点:
- 继承SpringBootServletInitializer是为了保留war包部署能力
- @SpringBootApplication等价于三个注解组合:
- @Configuration(标记配置类)
- @EnableAutoConfiguration(启用自动配置)
- @ComponentScan(包扫描)
4.2 配置迁移
将原有XML配置转换为JavaConfig或YAML:
传统web.xml配置:
<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> </filter>改造为配置类:
@Bean public FilterRegistrationBean<CharacterEncodingFilter> encodingFilter() { FilterRegistrationBean<CharacterEncodingFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new CharacterEncodingFilter()); bean.addInitParameter("encoding", "UTF-8"); bean.addUrlPatterns("/*"); return bean; }4.3 静态资源处理
SpringBoot默认静态资源路径:
- classpath:/static
- classpath:/public
- classpath:/resources
- classpath:/META-INF/resources
如果原有项目使用特殊目录,可以通过配置调整:
spring: web: resources: static-locations: classpath:/custom-static/5. 测试与部署
5.1 单元测试改造
将原有JUnit 4测试升级为JUnit 5:
@SpringBootTest class UserServiceTest { @Autowired private UserService userService; @Test void testGetUser() { User user = userService.getById(1L); assertNotNull(user); } }5.2 打包方式选择
根据需求选择打包方式:
- 可执行jar(默认):
mvn clean package - 传统war包:需修改pom.xml中packaging为war
5.3 生产级配置
添加actuator监控:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>配置application.yml开启健康检查:
management: endpoints: web: exposure: include: health,info,metrics endpoint: health: show-details: always6. 常见问题解决方案
6.1 依赖冲突排查
使用mvn命令分析依赖树:
mvn dependency:tree -Dincludes=com.fasterxml.jackson.core遇到冲突时可以通过exclusions排除:
<dependency> <groupId>problematic.group</groupId> <artifactId>problematic-artifact</artifactId> <exclusions> <exclusion> <groupId>conflict.group</groupId> <artifactId>conflict-artifact</artifactId> </exclusion> </exclusions> </dependency>6.2 启动时常见异常
- Bean创建失败:检查@ComponentScan范围是否包含相关包
- 端口占用:通过server.port指定新端口
- JDBC连接失败:检查spring.datasource配置格式
- 视图解析异常:确保模板引擎依赖正确引入
6.3 性能调优建议
- JVM参数配置:
server: tomcat: max-threads: 200 min-spare-threads: 10- 启用响应式压缩:
server: compression: enabled: true mime-types: text/html,text/xml,text/plain,application/json改造完成后,项目的启动时间从原来的15秒降低到3秒,部署流程简化为单个jar文件传输,监控端点让系统健康状况一目了然。过程中最大的收获是理解了SpringBoot"约定优于配置"的设计哲学,通过合理的默认值减少样板代码。对于仍在使用传统Maven项目的团队,建议分模块逐步迁移,可以先从非核心模块开始验证。