• 简谈Spring Boot3.0升级后的踩坑之旅,另附解决方案!


    注:本文基于 newbeemall 项目升级Spring Boot3.0踩坑总结而来。

    一. 编译报错,import javax.servlet.*; 不存在

    这个报错主要是Spring Boot3.0已经为所有依赖项从 Java EE 迁移到 Jakarta EE API,导致 servlet 包名的修改,Spring团队这样做的原因,主要是避免 Oracle 的版权问题,解决办法很简单,两步走:

    1 添加 jakarta.servlet 依赖

    1. <dependency>
    2. <groupId>jakarta.servlet</groupId>
    3. <artifactId>jakarta.servlet-api</artifactId>
    4. </dependency>
    1. 修改项目内所有代码的导入依赖

    1. 修改前:
    2. import javax.servlet.*
    3. 修改后:
    4. import jakarta.servlet.*

    二. 附带的众多依赖包升级,导致的部分代码写法过期报警

    2.1 Thymeleaf升级到3.1.0.M2,日志打印的报警

    1. 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.
    2. 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.

    可以看出作者很贴心,日志里已经给出了升级后的写法,修改如下:

    1. 修改前:
    2. <th:block th:include="admin/header :: header-fragment"/>
    3. 修改后:
    4. <th:block th:insert="~{admin/header :: header-fragment}"/>

    2.2 Thymeleaf升级到3.1.0.M2,后端使用 thymeleafViewResolver 手动渲染网页代码报错

    1. // 修改前 Spring Boot2.7
    2. WebContext ctx = new (request, response,
    3. request.getServletContext(), request.getLocale(), model.asMap());
    4. html = thymeleafViewResolver.getTemplateEngine().process("mall/seckill-list", ctx);

    上述代码中针对 WebContext 对象的创建报错,这里直接给出新版写法

    1. // 修改后 Spring Boot3.0
    2. JakartaServletWebApplication jakartaServletWebApplication = JakartaServletWebApplication.buildApplication(request.getServletContext());
    3. WebContext ctx = new WebContext(jakartaServletWebApplication.buildExchange(request, response), request.getLocale(), model.asMap());
    4. 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-发布说明 中

    这里给出两个解决方案:

    1. 等待第三方库适配 Spring Boot 3.0

    2. 按照 Spring Boot 3.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官方仓库,这里我就不得不动用我的小聪明,给出解决方案:

    1. 手动将原有的 MybatisSqlSessionFactoryBean 类代码复制到一个我们自己代码目录下新建的 MybatisSqlSessionFactoryBean 类,去掉 NestedIOException 依赖

    2. 数据源自动配置代码修改

    1. @Slf4j
    2. @EnableConfigurationProperties(MybatisPlusProperties.class)
    3. @EnableTransactionManagement
    4. @EnableAspectJAutoProxy
    5. @Configuration
    6. @MapperScan(basePackages = "ltd.newbee.mall.core.dao", sqlSessionFactoryRef = "masterSqlSessionFactory")
    7. public class HikariCpConfig {
    8. @Bean
    9. public MybatisPlusInterceptor mybatisPlusInterceptor() {
    10. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    11. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    12. return interceptor;
    13. }
    14. @Bean(name = "masterDataSource")
    15. @ConfigurationProperties(prefix = "spring.datasource.master")
    16. public DataSource masterDataSource() {
    17. return new HikariDataSource();
    18. }
    19. /**
    20. * @param datasource 数据源
    21. * @return SqlSessionFactory
    22. * @Primary 默认SqlSessionFactory
    23. */
    24. @Bean(name = "masterSqlSessionFactory")
    25. public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource datasource,
    26. Interceptor interceptor,
    27. MybatisPlusProperties properties) throws Exception {
    28. MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
    29. bean.setDataSource(datasource);
    30. // 兼容mybatis plus的自动配置写法
    31. bean.setMapperLocations(properties.resolveMapperLocations());
    32. if (properties.getConfigurationProperties() != null) {
    33. bean.setConfigurationProperties(properties.getConfigurationProperties());
    34. }
    35. if (StringUtils.hasLength(properties.getTypeAliasesPackage())) {
    36. bean.setTypeAliasesPackage(properties.getTypeAliasesPackage());
    37. }
    38. bean.setPlugins(interceptor);
    39. GlobalConfig globalConfig = properties.getGlobalConfig();
    40. bean.setGlobalConfig(globalConfig);
    41. log.info("------------------------------------------masterDataSource 配置成功");
    42. return bean.getObject();
    43. }
    44. @Bean("masterSessionTemplate")
    45. public SqlSessionTemplate masterSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
    46. return new SqlSessionTemplate(sqlSessionFactory);
    47. }
    48. }

    到这里,项目就能够正常跑起来了

    总结

    Spring Boot 3.0 升级带来了很多破坏性更改,把众多依赖升级到了最新,算是解决了一部分历史问题,也为了云原型需求,逐步适配 graalvm ,不管怎么样作为技术开发者,希望有更多的开发者来尝试 Spring Boot 3.0 带来的新变化。

  • 相关阅读:
    判断链表是否是环形链表
    Linux之ssh
    大型综合办公管理系统源码(OA+HR+CRM)源码免费分享
    Labelme环境搭建,对视频进行标注
    MIPI CSI-2笔记(17) -- 数据格式(RGB图像数据)
    「Qt Widget中文示例指南」如何创建一个计算器?(一)
    MySQL零基础从入门到精通(总)
    分库分表之MyCat安装启动
    Qt学习笔记详解(1)- 对象树与信号与槽
    springboot打war包
  • 原文地址:https://blog.csdn.net/Javatutouhouduan/article/details/128198978