# nine_surplus 升级方案:Spring Boot 化 + 可执行 Jar + JDK 升级 ## Context(背景与目标) `nine_surplus`(11.1 万行、900 个 Java 文件)目前是一个基于 **Spring 4.1 + SpringMVC + Hibernate 4.2 + javax.servlet/JSP + 外部 Tomcat 8.5** 的 Web 应用,技术栈停留在 2013 年。当前部署方式是打成 `lotteryServer.war` 丢进 `apache-tomcat-8.5.100`,且此项目还在本机用 JDK8 运行。 用户明确诉求: 1. **集成 Spring Boot**,引入内嵌 Tomcat 2. **打包成可一键执行 `java -jar` 的 jar**,不再依赖外部 Tomcat 3. **JDK 升级到 11/17** 4. 本次只升级 `nine_surplus`,另外两个模块(lotteryCapture/lotteryOpen)不动 推荐技术选型(已和用户目标对齐): - **Spring Boot 2.7.x**(Spring 5.3 + javax.servlet 命名空间,与现有 `javax.*` 代码完全兼容,避免 11 万行改名) - **Hibernate 5.6.x**(Boot 2.7 配套,替换已从 spring-orm 移除的 hibernate4 支持) - **内嵌 Tomcat 9.x**(由 spring-boot-starter-web 提供) - **JDK 11**(先升 11 稳妥运行,17 作为后续可选) - **JSP/HTML 页面与现有 Spring XML 配置尽量保留**,降低改动面 > 注意:不采用 Spring Boot 3(jakarta 命名空间),否则全部 `javax.*` 要改名,风险不可控。 --- ## 升级要点(改造点梳理) ### 1. 保留不动的内容(大块存量) - **59 个 JSP + 119 个 HTML 静态页**,原样保留(Boot 内嵌 Tomcat 可直接加载) - **spring-config.xml / spring-mvc.xml** 的 XML bean 定义,通过主类 `@ImportResource` 引导加载,不改业务 bean - **6 个支付/加密 system scope 黑盒 jar**:`cryptix-jce-provider`、`lzma-4.63-jio`、`dinpayRsaSignAPI`、`beecloud-java-sdk`、`yst_api`、`lzma`。这些是黑盒支付 SDK,改造时**不碰它们的实现**,仅确保能打进可执行 jar 的 classpath ### 2. 必须修改的部分 #### A. pom.xml 重构 | 项 | 现状 | 改后 | |----|------|------| | packaging | `war` | `jar` | | parent | 无 | `spring-boot-starter-parent:2.7.x` | | spring | 4.1.0.RELEASE | 由 Boot 2.7 管理(Spring 5.3.x,去掉显式 ``) | | hibernate | 4.2.13.Final | 5.6.x(Boot 管理,去掉 ``) | | 依赖 | 各 spring/hibernate 手动声明 | 合并为 starter:`spring-boot-starter-web`、`spring-boot-starter-data-jpa` 或保留 jdbc/hibernate;redis 用 `spring-boot-starter-data-redis` 或保留 spring-data-redis+jedis | | system scope jar | cryptix/lzma/dinpay/beecloud/yst | 保留,但需处理打入 jar(Boot 默认不打包 system scope,需 `maven-jar-plugin` 或 spring-boot-maven-plugin 的 exclude/include 配置) | | maven-jar-plugin mainClass | 无 | 填 `com.xxx.LotteryServerApplication` | | Web 插件 | `maven-war-plugin` / `tomcat7-maven-plugin` | 移除,改用 `spring-boot-maven-plugin` | **关键坑**:`LocalSessionFactoryBean` 从 `org.springframework.orm.hibernate4` 改为 `org.springframework.orm.hibernate5`。 #### B. 新增 Spring Boot 启动主类 新建 `LotteryServerApplication`(`@SpringBootApplication` + `@ImportResource("classpath:config/spring/spring-config.xml")`),并在其中: - `@Bean` 配置 spring-mvc 的 DispatcherServlet 映射(或通过配置类 `implements WebMvcConfigurer` 引入 spring-mvc.xml) - `@Bean` 注册 CharacterEncodingFilter、springSessionRepositoryFilter(替代 web.xml 中的 filter) - 可选:让主类 `extends SpringBootServletInitializer` 以保留双部署能力 #### C. Hibernate 5 适配(核心工作量) 集中在 DAO 基类,量小但关键: - [HibernateSuperDao.java](file:///c:/data/src/lottery/nine_surplus/nine_surplus/src/main/java/javautils/jdbc/hibernate/HibernateSuperDao.java) - [HibernateSuperReadDao.java](file:///c:/data/src/lottery/nine_surplus/nine_surplus/src/main/java/javautils/jdbc/hibernate/HibernateSuperReadDao.java) - 关注点:`getCurrentSession()`、`createCriteria`、`sessionFactory` 注入、事务管理器适配(`HibernateTransactionManager` → hibernate5 包) - spring-config.xml 中 3 个 `LocalSessionFactoryBean`(write/read/autoLoad)的 class 改为 hibernate5,`hibernate.cache.provider_class` 等属性检查 #### D. WebSocket 适配 - [WebSocketConfig.java](file:///c:/data/src/lottery/nine_surplus/nine_surplus/src/main/java/lottery/web/websocket/WebSocketConfig.java) 用 `@EnableWebSocket`(Spring 自带,非原生 javax.websocket),Boot 2.7 兼容,基本无需改;仅确认 handler 依赖的容器对象注入方式 #### E. 资源/配置加载 - `EncryptPropertyPlaceholderConfigurer`(显式读取 `.properties` + 解密)在 Boot 下需适配为 `PropertySourcesPlaceholderConfigurer` 风格或保留自定义类,确认 `${...}` 占位符在 Boot 环境正常解析 - 确认 `config/datasource/*.properties`、`config/hibernate/*` 的 classpath 路径在打包 jar 后仍在类路径上 --- ## 推荐实施步骤(分批执行) 1. **备份**:先对 `nine_surplus` 目录做完整备份 / 用 git 分支,确保可回滚 2. **pom 改造 + 主类骨架**:改 packaging、引入 Boot parent/starter、新增 `LotteryServerApplication`,先让应用能`mvn spring-boot:run` 起来(不急着全功能) 3. **Hibernate 5 适配**:替换 DAO 基类与 spring-config 中的 hibernate4→hibernate5,编译通过 4. **Filter/DispatcherServlet 注册**:把 web.xml 里的 filter、servlet 迁移到 Boot 主类/配置类 5. **system jar 打包确认**:验证支付 SDK 能被可执行 jar 正确加载 6. **JDK 11 验证**:`mvn clean package` 产出可执行 jar,`java -jar lotteryServer.jar` 启动成功,访问登录页 7. **回归测试**:登录、下单、余额/报表等核心链路 + Redis 会话 + WebSocket ## 代表性关键文件 - `nine_surplus/pom.xml`(重构) - `nine_surplus/src/main/webapp/WEB-INF/web.xml`(配置迁移参照,可删除) - `nine_surplus/src/main/resources/config/spring/spring-config.xml`、`spring-mvc.xml`(保留 + hibernate5 适配) - 新增 `LotteryServerApplication.java` - `javautils/jdbc/hibernate/HibernateSuperDao.java`、`HibernateSuperReadDao.java`(Hibernate5 适配) - `lottery/web/websocket/WebSocketConfig.java`(确认兼容) --- ## 验证方式 1. `mvn -f pom.xml clean package` 成功产出可执行 jar 2. `java -jar target/lotteryServer.jar`(JDK11)启动,无 ClassNotFound/NoSuchMethod 异常 3. 浏览器访问 `http://localhost:8080/`(或配置端口)能返回登录页(原 war 是 8080) 4. 确认 Redis 会话、WebSocket、支付回调等核心链路可用 5. 用 `jvisualvm`/启动日志确认内嵌 Tomcat 正常监听端口 ## 风险与明确边界 - **不会做**:不搬到 Spring Boot 3 / jakarta、不迁移 Thymeleaf、不重写 11 万行业务代码、不处理另两个模块 - **高危点**:Hibernate 4→5 的 API 差异(主要在 2 个 DAO 基类 + 事务管理器)、system 支付 jar 的兼容性、`EncryptPropertyPlaceholderConfigurer` 解密在 Boot 环境的解析 - **如遇 system jar 在 JDK11 上不兼容**(黑盒无从修改):降级方案是仅 JDK 升级到 11、保留 war,Boot 化分阶段单独进行,避免一次全上