news 2026/4/18 5:00:26

保姆级教程:手把手教你将若依前后端分离版从Java 8平滑升级到Java 17(含Spring Security 6.2.3适配)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
保姆级教程:手把手教你将若依前后端分离版从Java 8平滑升级到Java 17(含Spring Security 6.2.3适配)

保姆级教程:手把手教你将若依前后端分离版从Java 8平滑升级到Java 17(含Spring Security 6.2.3适配)

最近在技术社区看到不少开发者讨论Java 17的新特性,尤其是对LTS版本长期支持的期待。作为一个长期使用若依框架的开发者,我决定将手头的项目从Java 8升级到Java 17。整个过程花了三天时间,踩了不少坑,也积累了一些经验。今天就把这个完整的升级过程记录下来,希望能帮助到有同样需求的同行。

升级Java版本看似简单,但实际上涉及到整个技术栈的适配,特别是像若依这样集成了Spring Boot、MyBatis Plus、Spring Security等主流框架的系统。我们需要考虑的不仅仅是JDK本身的变更,还有依赖库的兼容性、配置语法的变化,以及Jakarta EE的迁移问题。

1. 环境准备与依赖分析

在开始升级之前,我们需要做好充分的准备工作。首先确保你的开发环境已经安装了Java 17 JDK,我推荐使用Amazon Corretto 17或者OpenJDK 17。可以通过以下命令验证:

java -version

你应该看到类似这样的输出:

openjdk version "17.0.10" 2024-01-16 OpenJDK Runtime Environment (build 17.0.10+7) OpenJDK 64-Bit Server VM (build 17.0.10+7, mixed mode)

接下来,我们需要分析当前项目的依赖树,找出可能需要升级的组件。在项目根目录下运行:

mvn dependency:tree > dependency.txt

这个命令会把项目的完整依赖树输出到dependency.txt文件中。仔细检查这个文件,特别关注以下几个关键依赖:

  • Spring Boot版本(需要升级到3.x系列)
  • Spring Security版本
  • MyBatis Plus版本
  • 数据库驱动(如MySQL Connector/J)
  • Servlet API相关依赖

常见需要升级的依赖清单

  • Spring Boot: 2.x → 3.2.5
  • Spring Security: 5.x → 6.2.3
  • MyBatis Plus: 3.4.x → 3.5.5
  • MySQL Connector/J: 5.x → 8.1.0
  • Logback: 1.2.x → 1.4.14

提示:建议在升级前创建一个新的Git分支,这样如果升级过程中出现问题可以随时回退。

2. 分模块修改POM文件

若依前后端分离版通常包含多个模块:ruoyi-admin、ruoyi-common、ruoyi-framework等。我们需要逐个模块进行升级。

2.1 父POM的修改

首先修改父POM中的属性定义,这是整个升级过程中最关键的一步。我们需要更新Java版本和主要依赖的版本号:

<properties> <java.version>17</java.version> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <spring-boot.version>3.2.5</spring-boot.version> <mybatis.plus.version>3.5.5</mybatis.plus.version> <tomcat.version>10.1.24</tomcat.version> <logback.version>1.4.14</logback.version> <spring-security.version>6.2.3</spring-security.version> <spring-framework.version>6.2.6</spring-framework.version> <mysql-connector-j.version>8.1.0</mysql-connector-j.version> <jakarta.servlet-api.version>6.0.0</jakarta.servlet-api.version> <mybatis-spring.version>3.0.3</mybatis-spring.version> </properties>

然后更新dependencyManagement部分,确保所有子模块使用统一的依赖版本:

<dependencyManagement> <dependencies> <!-- 阿里数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-3-starter</artifactId> <version>${druid.version}</version> </dependency> <!-- servlet --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>${jakarta.servlet-api.version}</version> </dependency> <!-- mysql --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>${mysql-connector-j.version}</version> </dependency> <!-- MyBatis相关 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis-spring.version}</version> </dependency> </dependencies> </dependencyManagement>

2.2 子模块POM的修改

ruoyi-admin模块主要需要更新MySQL驱动:

<dependencies> <!-- Mysql驱动包 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> </dependency> </dependencies>

ruoyi-common模块需要更新Servlet API:

<dependencies> <!-- servlet包 --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> </dependency> </dependencies>

ruoyi-framework模块需要特别注意Druid连接池的版本:

<dependencies> <!-- 阿里数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-3-starter</artifactId> </dependency> <!-- 验证码 --> <dependency> <groupId>pro.fessional</groupId> <artifactId>kaptcha</artifactId> <exclusions> <exclusion> <artifactId>servlet-api</artifactId> <groupId>jakarta.servlet</groupId> </exclusion> </exclusions> </dependency> </dependencies>

注意:从Spring Boot 3开始,很多依赖的groupId或artifactId发生了变化,特别是Jakarta EE相关的包名从javax.改为了jakarta.

3. Spring Security 6.2.3适配

Spring Security 6.x相对于5.x有较大的API变化,这是升级过程中最具挑战性的部分之一。我们需要重点关注安全配置类的修改。

3.1 SecurityConfig的修改

最明显的变化是.antMatchers()方法被.requestMatchers()取代。下面是新旧代码对比:

旧版配置

.authorizeRequests() .antMatchers("/login", "/register", "/captchaImage").permitAll() .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() .anyRequest().authenticated();

新版配置

.authorizeHttpRequests((requests) -> { requests.requestMatchers("/login", "/register", "/captchaImage").permitAll() .requestMatchers(HttpMethod.GET, "/", "/*.html", "/**.html", "/**.css", "/**.js").permitAll() .anyRequest().authenticated(); })

完整的SecurityConfig类修改示例:

@Bean protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { return httpSecurity // CSRF禁用,因为不使用session .csrf(AbstractHttpConfigurer::disable) // 禁用HTTP响应标头 .headers(header -> header .cacheControl(HeadersConfigurer.CacheControlConfig::disable) .frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) // 认证失败处理类 .exceptionHandling(exception -> exception .authenticationEntryPoint(unauthorizedHandler)) // 基于token,所以不需要session .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 注解标记允许匿名访问的url .authorizeHttpRequests((requests) -> { permitAllUrl.getUrls().forEach(url -> requests.requestMatchers(url).permitAll()); requests.requestMatchers("/login", "/register", "/captchaImage").permitAll() .requestMatchers(HttpMethod.GET, "/", "/*.html", "/**.html", "/**.css", "/**.js", "/profile/**").permitAll() .requestMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() .anyRequest().authenticated(); }) // 添加Logout filter .logout(logout -> logout .logoutUrl("/logout") .logoutSuccessHandler(logoutSuccessHandler)) // 添加JWT filter .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class) // 添加CORS filter .addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class) .addFilterBefore(corsFilter, LogoutFilter.class) .build(); }

3.2 PermitAllUrlProperties的修改

Spring Security 6.x中获取请求映射的方式也发生了变化:

@Override public void afterPropertiesSet() { // 修改前 // RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class); // 修改后 RequestMappingHandlerMapping mapping = applicationContext.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class); Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods(); map.keySet().forEach(info -> { HandlerMethod handlerMethod = map.get(info); // 获取方法上边的注解 Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class); Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPathPatternsCondition().getPatternValues()) .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK)))); // 获取类上边的注解 Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPathPatternsCondition().getPatternValues()) .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK)))); }); }

4. Jakarta EE迁移与验证

从Java EE到Jakarta EE的包名变更是一个重大变化,我们需要检查所有javax.的导入并替换为jakarta.

4.1 Servlet API变更

修改DruidConfig中的导入语句:

// 修改前 // import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; // import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; // 修改后 import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceBuilder; import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;

4.2 验证升级结果

完成所有修改后,我们需要验证系统功能是否正常:

  1. 编译验证

    mvn clean compile

    确保没有编译错误。

  2. 单元测试

    mvn test

    运行所有单元测试,确保核心逻辑仍然正常工作。

  3. 功能验证

    • 启动应用:mvn spring-boot:run
    • 测试登录功能
    • 验证权限控制是否正常
    • 检查数据库连接是否正常
    • 测试文件上传下载等Servlet相关功能

常见问题排查

  • 如果遇到ClassNotFound异常,检查是否所有javax.的导入都已替换为jakarta.
  • 如果Spring Security配置不生效,检查是否所有.antMatchers()都已改为.requestMatchers()
  • 如果数据库连接失败,检查MySQL驱动版本和连接参数

提示:建议在升级完成后运行完整的回归测试,特别是权限相关的功能点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 5:00:16

若依WMS仓库管理系统:5步快速部署与核心功能全解析

若依WMS仓库管理系统&#xff1a;5步快速部署与核心功能全解析 【免费下载链接】RuoYi-WMS-VUE 若依wms是一套基于若依的wms仓库管理系统&#xff0c;支持lodop和网页打印入库单、出库单。包括仓库/库区/货架管理&#xff0c;出入库管理&#xff0c;客户/供应商/承运商&#xf…

作者头像 李华
网站建设 2026/4/18 4:59:14

Altium Designer 24 总线设计规范与 Error Reporting 实战避坑指南

1. Altium Designer 24 总线设计规范入门 刚接触Altium Designer 24的总线设计时&#xff0c;我踩过不少坑。记得第一次画总线原理图&#xff0c;编译后弹出的错误信息看得我头皮发麻。后来才发现&#xff0c;掌握总线设计规范是高效使用AD24的关键。 总线在电路设计中就像城市…

作者头像 李华
网站建设 2026/4/18 4:52:56

【JVM深度解析】第30篇:GraalVM与AOT编译

摘要 GraalVM 被称为"VM 的 VM"&#xff0c;它不仅能运行 Java 字节码&#xff0c;还能运行 JavaScript、Python、Ruby、R 等多语言代码。更重要的是&#xff0c;GraalVM 的 AOT&#xff08;Ahead-Of-Time&#xff09;编译可以将 Java 应用编译成原生可执行文件&…

作者头像 李华
网站建设 2026/4/18 4:49:25

如何截断SQL小数位数_使用TRUNCATE函数控制精度

MySQL的TRUNCATE是DDL命令&#xff0c;不可截小数&#xff1b;PostgreSQL和SQL Server支持TRUNCATE(value,decimals)数值截断。MySQL需用TRUNCATE()函数&#xff08;非DDL&#xff09;、FLOOR缩放或CAST转DECIMAL&#xff0c;三者对负数和精度处理不同。TRUNCATE 函数在 MySQL …

作者头像 李华
网站建设 2026/4/18 4:47:13

从凸包到对话:深入解析Pointer Network如何革新序列生成任务

1. 从几何问题到序列生成&#xff1a;Pointer Network的诞生背景 我第一次接触Pointer Network是在解决一个看似简单的几何问题时——计算给定点集的凸包。传统算法虽然能完美解决&#xff0c;但当我尝试用神经网络实现时&#xff0c;立刻遇到了seq2seq模型的致命缺陷&#xff…

作者头像 李华