若依升级到springboot3
声明:本文章为学习总结,不合理和错误之处还请指正
本文使用到的若依为前后分离版,JDK必须>=17
pom文件及相关依赖的变更
<java.version>17</java.version>
1. springboot使用3.1.0版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
<relativePath />
</parent>
2. druid版本更新到1.2.18并使用druid-spring-boot-3-starter
<druid.version>1.2.18</druid.version>
旧版本
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
新版本
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>${druid.version}</version>
</dependency>
在src/main/resources/META-INF目录下创建spring文件夹和org.springframework.boot.autoconfigure.AutoConfiguration.imports文件 imports文件内容为com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure
3. pom文件添加新依赖
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.2</version>
</dependency>
4.替换新的quartz依赖
旧版本
<!-- 定时任务 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<exclusions>
<exclusion>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
</exclusion>
</exclusions>
</dependency>
新版本
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
5.新增javax.xml.bind依赖
<jaxb-api.version>2.3.0</jaxb-api.version>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-api.version}</version>
</dependency>
6.jaxb-api更新版本
<pagehelper.spring.boot.starter.version>1.4.6</pagehelper.spring.boot.starter.version>
代码的变更
1.javaee转jakara
SpringBoot3开始,所有的Java EE Api都需要迁移到Jakarta EE上来,需要jakarta替换原先报红的javax
idea提供了该功能:
2.SecurityConfig文件修改
类上注解过期需更新,删除 extends WebSecurityConfigurerAdapter
旧版本
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
新版本
@Configuration
@EnableWebSecurity
public class SecurityConfig
旧版本
/**
* 解决 无法直接注入 AuthenticationManager
*
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
新版本
@Bean
AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
旧版本
/**
* anyRequest | 匹配所有请求路径
* access | SpringEl表达式结果为true时可以访问
* anonymous | 匿名可以访问
* denyAll | 用户不能访问
* fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
* hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
* hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
* hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
* hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
* hasRole | 如果有参数,参数表示角色,则其角色可以访问
* permitAll | 用户可以任意访问
* rememberMe | 允许通过remember-me登录的用户访问
* authenticated | 用户登录后可访问
*/
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
httpSecurity
// CSRF禁用,因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/register", "/captchaImage").anonymous()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/profile/**"
).permitAll()
.antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs").anonymous()
.antMatchers("/druid/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}
新版本(注意新的spring已经弃用了AntPath配置模式,默认使用pathPattern;pathPattern无法使用 ** 匹配任意层级目录,以下都改为一个 *
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers("/login", "/register", "/captchaImage").anonymous()
.requestMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/*/*.html",
"/*/*.css",
"/*/*.js",
"/profile/*").permitAll()
.requestMatchers("/swagger-ui.html","/swagger-resources/*","/webjars/*","/*/api-docs","/druid/*").anonymous()
.anyRequest().authenticated()
)
// CSRF禁用,因为不使用session
.csrf(csrfConfigurer -> csrfConfigurer.disable()
)
// 认证失败处理类
.exceptionHandling(exceptionConfigurer -> exceptionConfigurer.authenticationEntryPoint(unauthorizedHandler))
// 基于token,所以不需要session
.sessionManagement(sessionConfigurer -> sessionConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.headers(headersConfigurer -> headersConfigurer.frameOptions(frameOptionsConfig -> frameOptionsConfig.disable()))
.logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.logoutSuccessHandler(logoutSuccessHandler))
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
// 添加CORS filter
.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
.addFilterBefore(corsFilter, LogoutFilter.class)
;
return http.build();
}
注释该方法
/**
* 身份认证接口
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
3.ResourcesConfig文件修改
旧版本
// 设置访问源地址
config.addAllowedOrigin("*");
新版本
// 设置访问源地址
config.addAllowedOriginPattern("*");
4.quartz 配置修改
不使用ScheduleConfig类,可注释
在DruidConfig文件中dynamicDataSource的bean上加入@QuartzDataSource注解 新版本
@Bean(name = "dynamicDataSource")
@QuartzDataSource
@Primary
public DynamicDataSource dataSource(DataSource masterDataSource)
{
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
return new DynamicDataSource(masterDataSource, targetDataSources);
}
到这里,应该就可以运行了。