当前位置: 首页 > news >正文

Ruoyi-Vue 升级JDK21、Springboot3、Mybatis3

一、需要升级的组件

名称原版本目标版本
JDK1.821
Springboot、Redis2.5.133.2.5
Servlet4.0.16.0.0
Mybatis2.0.73.0.3
Mysql驱动8.0.288.3.0
Lombok1.18.201.18.30
Kaptcha2.3.22.3.3
Flowable1.821
jaxb-api2.3.02.3.1

二、详细说明

JDK
<java.version>1.8</java.version><!-- ↓↓↓改为下面↓↓↓ --><java.version>21</java.version>
Springboot、Redis
<springboot.version>2.5.13</springboot.version><!-- ↓↓↓改为下面↓↓↓ --><springboot.version>3.2.5</springboot.version>
Servlet

依赖调整

<!-- servlet包 -->
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId>
</dependency><!-- ↓↓↓改为下面↓↓↓ --><dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</artifactId>
</dependency>

全局包名更换

javax.servlet  →  jakarta.servletjavax.validation  →  jakarta.validationjavax.annotation  →  jakarta.annotation
Mybatis
<mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version><!-- ↓↓↓改为下面↓↓↓ --><mybatis-spring-boot.version>3.0.3</mybatis-spring-boot.version>
Mysql驱动
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency><!-- ↓↓↓改为下面↓↓↓ --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId>
</dependency>
Lombok
<lombok.version>1.18.20</lombok.version><!-- ↓↓↓改为下面↓↓↓ --><lombok.version>1.18.30</lombok.version>
Kaptcha
<kaptcha.version>2.3.2</kaptcha.version>
<!-- ↓↓↓改为下面↓↓↓ -->
<kaptcha.version>2.3.3</kaptcha.version><!-- 验证码 -->
<dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>${kaptcha.version}</version>
</dependency><!-- ↓↓↓改为下面↓↓↓ --><!-- 验证码 --><dependency><groupId>pro.fessional</groupId><artifactId>kaptcha</artifactId><exclusions><exclusion><artifactId>servlet-api</artifactId><groupId>jakarta.servlet</groupId></exclusion></exclusions></dependency>
Easy-captcha
<dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId><version>1.6.2</version>
</dependency><!-- ↓↓↓后面添加↓↓↓ --><dependency><groupId>org.openjdk.nashorn</groupId><artifactId>nashorn-core</artifactId><version>15.4</version>
</dependency>
Flowable
<dependency><groupId>org.flowable</groupId><artifactId>flowable-engine</artifactId><version>6.7.2</version>
</dependency>
<dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter-basic</artifactId><version>6.7.2</version>
</dependency><!-- ↓↓↓改为下面↓↓↓ --><dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter</artifactId><version>7.1.0</version>
</dependency>
jaxb-api
<dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version>
</dependency><!-- ↓↓↓后面添加↓↓↓ --><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version>
</dependency>

三、相关配置类调整

PermitAllUrlProperties
@Configuration
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware {private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");private ApplicationContext applicationContext;private List<String> urls = new ArrayList<>();public String ASTERISK = "*";@Overridepublic void afterPropertiesSet() {RequestMappingHandlerMapping mapping = applicationContext.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();map.keySet().forEach(info -> {HandlerMethod handlerMethod = map.get(info);// 获取方法上边的注解 替代path variable 为 *Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
//            Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
//                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));Optional.ofNullable(method).flatMap(anonymous -> Optional.ofNullable(info.getPatternsCondition())).ifPresent(patterns -> patterns.getPatterns().forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));// 获取类上边的注解, 替代path variable 为 *Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
//            Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
//                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));Optional.ofNullable(controller).flatMap(anonymous -> Optional.ofNullable(info.getPatternsCondition())).ifPresent(patterns -> patterns.getPatterns().forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));});}@Overridepublic void setApplicationContext(ApplicationContext context) throws BeansException {this.applicationContext = context;}public List<String> getUrls() {return urls;}public void setUrls(List<String> urls) {this.urls = urls;}
}
SecurityConfig
@Configuration
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {/*** 允许匿名访问的地址*/@Resourceprivate PermitAllUrlProperties permitAllUrl;/*** 自定义用户认证逻辑*/@Resourceprivate UserDetailsService userDetailsService;/*** 认证失败处理类*/@Resourceprivate AuthenticationEntryPointImpl unauthorizedHandler;/*** 退出处理类*/@Resourceprivate LogoutSuccessHandlerImpl logoutSuccessHandler;/*** token认证过滤器*/@Resourceprivate JwtAuthenticationTokenFilter authenticationTokenFilter;/*** 跨域过滤器*/@Resourceprivate CorsFilter corsFilter;@Beanpublic AuthenticationManager authenticationManagerBean(){DaoAuthenticationProvider provider = new DaoAuthenticationProvider();provider.setUserDetailsService(userDetailsService);provider.setPasswordEncoder(bCryptPasswordEncoder());return new ProviderManager(provider);}/*** anyRequest          |   匹配所有请求路径* access              |   SpringEl表达式结果为true时可以访问* anonymous           |   匿名可以访问* denyAll             |   用户不能访问* fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)* hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问* hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问* hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问* hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问* hasRole             |   如果有参数,参数表示角色,则其角色可以访问* permitAll           |   用户可以任意访问* rememberMe          |   允许通过remember-me登录的用户访问* authenticated       |   用户登录后可访问*/@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {// CSRF禁用,因为不使用sessionhttp.csrf(AbstractHttpConfigurer::disable)// authenticationEntryPoint认证失败处理类;accessDeniedHandler授权失败.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))// 基于token,所以不需要session.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))// 过滤请求// 对于登录login 允许匿名访问,但是如果携带认证token反而不能访问.authorizeHttpRequests(auth -> {permitAllUrl.getUrls().forEach(url -> auth.requestMatchers(url).permitAll());auth.requestMatchers("/login", "/app-user/login").anonymous().requestMatchers(HttpMethod.GET,"/","/*.html","/**.html","/*.css",// 前端資源放行"/static/**",// 由于安卓手机微信公众号页面无法实现blog二进制流的读取下载pdf,// 故这里暂时先放开,后续有客户沟通是否需要做公众号卡号绑定业务增强安全性"/*.js",// 文件上傳路徑放行"/captcha/*","/home/management/uploadPath/**`").permitAll()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();}).headers(AbstractHttpConfigurer::disable);//注销配置,退出后跳转到/logout,退出成功后处理logoutSuccessHandlerhttp.logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler));// 添加JWT filter,添加该过滤器放在UsernamePasswordAuthenticationFilter过滤器之前http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);// 添加CORS filterhttp.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);http.addFilterBefore(corsFilter, LogoutFilter.class);return http.build();}/*** 强散列哈希加密实现,这里会使得密码校验的时候默认使用该加密实现*/@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder() {return new BCryptPasswordEncoder();}
application.yml

redis配置

spring:data:  # ←----- ######## 改动在这里,多了一级data ########## redis配置redis:# 地址host: localhostport: 6379# 数据库索引database: 2# 密码password: # 连接超时时间timeout: 10slettuce:pool:# 连接池中的最小空闲连接min-idle: 0# 连接池中的最大空闲连接max-idle: 8# 连接池的最大数据库连接数max-active: 8# #连接池最大阻塞等待时间(使用负值表示没有限制)max-wait: -1ms
pom.yml

maven打包插件

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration>
</plugin><!-- ↓↓↓改为下面↓↓↓ --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>${java.version}</source><target>${java.version}</target><encoding>${project.build.sourceEncoding}</encoding><compilerArgs>   <!--←----- ######## 改动在这里,加了这个配置 ######### --><arg>-parameters</arg></compilerArgs></configuration>
</plugin>

四、补充

  1. 项目启动报错
    Failed to start bean ‘documentationPluginsBootstrapper‘; nested exception is java.lang.NullPointerException

解决:暂时关闭swagger 或 升级
在这里插入图片描述

  1. 循环依赖问题
    解决:加@Lasy注解或根据实际业务情况调整代码调用

  2. 验证码问题
    在这里插入图片描述
    解决:添加解析器(上面已提到)

<dependency><groupId>org.openjdk.nashorn</groupId><artifactId>nashorn-core</artifactId><version>15.4</version>
</dependency>
  1. 还有其它报错,可根据具体错误信息查看源码、百度、大模型解决,提升解决问题能力。相信自己是最棒的!!

相关文章:

  • tp5被黑做的网站全变成首页宁波seo超级外链工具
  • 银川建企业模板网站网站搜索排名优化怎么做
  • 电子商务网站策划seo技术博客
  • 网站建设现状分析关键词排名方法
  • 做网站阳泉免费刷粉网站推广
  • 重庆建设银行官方网站首页百度网络营销中心app
  • 【GStreamer】减小延时的参数设置、从RTP中获取时间戳
  • 鸿蒙ArkUI---基础组件Tabs(Tabbar)
  • 用Rust写平衡三进制乘法器
  • Linux size命令详解
  • PYTHON从入门到实践6-字典
  • 使用 EasySearch 构建 RAG(检索增强生成)系统
  • 根据不同的环境打包
  • 西班牙证券交易所智能交易系统开发报告
  • 化于无形的 lambda 语法
  • 【网站内容安全检测】之2:从网站所有URL页面中提取所有外部及内部域名信息
  • Django
  • 写入P99延迟突破1秒含义
  • MySQL原理--Hash索引和B+树索引的区别
  • 碳化硅MOS四开关 Buck-Boost DC-DC 变换器
  • 在cmake中指定clang编译cuda文件
  • TensorFlow深度学习实战:构建神经网络全指南
  • 企业内部安全组网技术解析:安全通道选型、零信任架构与数据合规加密防护
  • Linux RDMA网络配置手册
  • 11 MySQL 如何优化数据查询方案?
  • Cookie 在 HTTP 中的作用HTTP 中的状态码