本文基于 newbeemall 專案升級Spring Boot3.0踩坑總結而來,附帶更新說明:
Spring-Boot-3.0-發布說明
Spring-Boot-3.0.0-M5-發布說明
一. 編譯報錯,import javax.servlet.*; 不存在
這個報錯主要是Spring Boot3.0已經為所有依賴項從 Java EE 遷移到 Jakarta EE API,導致 servlet 包名的修改,Spring團隊這樣做的原因,主要是避免 Oracle 的著作權問題,解決辦法很簡單,兩步走:
1 添加 jakarta.servlet 依賴
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
- 修改專案內所有代碼的匯入依賴
修改前:
import javax.servlet.*
修改后:
import jakarta.servlet.*
二. 附帶的眾多依賴包升級,導致的部分代碼寫法過期報警
2.1 Thymeleaf升級到3.1.0.M2,日志列印的報警
14:40:39.936 [http-nio-84-exec-15] WARN o.t.s.p.StandardIncludeTagProcessor - [doProcess,67] - [THYMELEAF][http-nio-84-exec-15][admin/goods/goods] Deprecated attribute {th:include,data-th-include} found in template admin/goods/goods, line 4, col 15. Please use {th:insert,data-th-insert} instead, this deprecated attribute will be removed in future versions of Thymeleaf.
14:40:39.936 [http-nio-84-exec-15] WARN o.t.s.p.AbstractStandardFragmentInsertionTagProcessor - [computeFragment,385] - [THYMELEAF][http-nio-84-exec-15][admin/goods/goods] Deprecated unwrapped fragment expression "admin/header :: header-fragment" found in template admin/goods/goods, line 4, col 15. Please use the complete syntax of fragment expressions instead ("~{admin/header :: header-fragment}"). The old, unwrapped syntax for fragment expressions will be removed in future versions of Thymeleaf.
可以看出作者很貼心,日志里已經給出了升級后的寫法,修改如下:
修改前:
<th:block th:include="admin/header :: header-fragment"/>
修改后:
<th:block th:insert="~{admin/header :: header-fragment}"/>
2.2 Thymeleaf升級到3.1.0.M2,后端使用 thymeleafViewResolver 手動渲染網頁代碼報錯
// 修改前 Spring Boot2.7:
WebContext ctx = new (request, response,
request.getServletContext(), request.getLocale(), model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("mall/seckill-list", ctx);
上述代碼中針對 WebContext 物件的創建報錯,這里直接給出新版寫法
// 修改后 Spring Boot3.0:
JakartaServletWebApplication jakartaServletWebApplication = JakartaServletWebApplication.buildApplication(request.getServletContext());
WebContext ctx = new WebContext(jakartaServletWebApplication.buildExchange(request, response), request.getLocale(), model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("mall/seckill-list", ctx);
三. 大量第三方庫關于 Spring Boot 的 starter 依賴失效,導致專案啟動報錯
博主升級到3.0后,發現啟動時,Druid 資料源開始報錯,找不到資料源配置,便懷疑跟 Spring boot 3.0 更新有關
這里直接給出原因:Spring Boot 3.0 中自動配置注冊的 spring.factories 寫法已廢棄,改為了 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 寫法,導致大量第三方 starter 依賴失效
在吐槽一下,這么重要的更改在Spring官方的 Spring-Boot-3.0-發布說明 中竟然沒有,被放在了 Spring-Boot-3.0.0-M5-發布說明 中
這里給出兩個解決方案:
- 等待第三方庫適配
Spring Boot3.0 - 按照
Spring Boot3.0要求,在專案resources下新建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports檔案,手動將第三方庫的spring.factories加到imports中,這樣可以手動修復第三方庫spring boot starter依賴失效問題
四. Mybatis Plus 依賴問題
Mybatis plus 最新版本還是3.5.2,其依賴的 mybatis-spring 版本是2.2.2(mybatis-spring 已經發布了3.0.0版本適配 Spring Boot 3.0),這會導致專案中的sql查詢直接報錯,這里主要是因 Spring Boot 3.0中洗掉 NestedIOException 這個類,在 Spring boot 2.7中這個類還存在,給出類說明截圖
這個類在2.7中已經被標記為廢棄,建議替換為 IOException, 而 Mybatis plus 3.5.2中還在使用,這里給出問題截圖 MybatisSqlSessionFactoryBean 這個類還在使用 NestedIOException
查看 Mybatis plus 官方issue也已經有人提到了這個問題,官方的說法是 mybatis-plus-spring-boot-starter 還在驗證尚未推送maven官方倉庫,這里我就不得不動用我的小聰明,給出解決方案:
- 手動將原有的
MybatisSqlSessionFactoryBean類代碼復制到一個我們自己代碼目錄下新建的MybatisSqlSessionFactoryBean類,去掉NestedIOException依賴 - 資料源自動配置代碼修改
@Slf4j
@EnableConfigurationProperties(MybatisPlusProperties.class)
@EnableTransactionManagement
@EnableAspectJAutoProxy
@Configuration
@MapperScan(basePackages = "ltd.newbee.mall.core.dao", sqlSessionFactoryRef = "masterSqlSessionFactory")
public class HikariCpConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return new HikariDataSource();
}
/**
* @param datasource 資料源
* @return SqlSessionFactory
* @Primary 默認SqlSessionFactory
*/
@Bean(name = "masterSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource datasource,
Interceptor interceptor,
MybatisPlusProperties properties) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(datasource);
// 兼容mybatis plus的自動配置寫法
bean.setMapperLocations(properties.resolveMapperLocations());
if (properties.getConfigurationProperties() != null) {
bean.setConfigurationProperties(properties.getConfigurationProperties());
}
if (StringUtils.hasLength(properties.getTypeAliasesPackage())) {
bean.setTypeAliasesPackage(properties.getTypeAliasesPackage());
}
bean.setPlugins(interceptor);
GlobalConfig globalConfig = properties.getGlobalConfig();
bean.setGlobalConfig(globalConfig);
log.info("------------------------------------------masterDataSource 配置成功");
return bean.getObject();
}
@Bean("masterSessionTemplate")
public SqlSessionTemplate masterSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
到這里,專案就能夠正常跑起來了
總結
Spring Boot 3.0 升級帶來了很多破壞性更改,把眾多依賴升級到了最新,算是解決了一部分歷史問題,也為了云原型需求,逐步適配 graalvm ,不管怎么樣作為技術開發者,希望有更多的開發者來嘗試 Spring Boot 3.0 帶來的新變化,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/539149.html
標籤:其他
