• Springboot项目升级2.2.x升至2.7.x


    依赖管理

    spring-boot-starter-parent 升级为2.7.1

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <!-- 升级为2.7.x的版本-->
    5. <version>2.7.1</version>
    6. <relativePath/> <!-- lookup parent from repository -->
    7. </parent>

    兼容老的配置文件格式,spring提供了专门的依赖进行兼容,但是建议还是在升级能成功运行之后进行配置的同步修改

    1. <!-- 升级2.7后支持yml环境变量名兼容-->
    2. <dependency>
    3. <groupId>org.springframework.boot</groupId>
    4. <artifactId>spring-boot-properties-migrator</artifactId>
    5. <scope>runtime</scope>
    6. </dependency>

    如果使用了bootstrap.yml文件,升级之后默认是不会使用bootstrap.yml了,所以可能会导致启动之后配置没有生效,需要引入依赖

    1. <dependency>
    2. <groupId>org.springframework.cloud</groupId>
    3. <artifactId>spring-cloud-starter-bootstrap</artifactId>
    4. <version>3.0.4</version>
    5. </dependency>

    配置修改

    2.7.x不会处理循环依赖问题,需要手动配置修改application.yml添加配置spring.main.allow-circular-references

    如果有nacos的使用,版本替换为:

    1. <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-config -->
    2. <dependency>
    3. <groupId>com.alibaba.cloud</groupId>
    4. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    5. <version>2021.0.4.0</version>
    6. </dependency>
    7. <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-discovery -->
    8. <dependency>
    9. <groupId>com.alibaba.cloud</groupId>
    10. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    11. <version>2021.0.4.0</version>
    12. </dependency>

    同时需要支持yml配置,添加 spring.config.import

    1. spring:
    2. profiles:
    3. active: "@profileActive@"
    4. application:
    5. name: saas
    6. cloud:
    7. nacos:
    8. server-addr: xx.xx.xx.xx:8848
    9. discovery:
    10. server-addr: xx.xx.xx.xx:8848
    11. namespace: f8f5c0c4-adc9-4c37-be6b-ddc
    12. config:
    13. server-addr: xx.xx.xx.xx:8848 #配置中心
    14. file-extension: yaml #配置文件后缀名 dataId = application.name + file-extension
    15. namespace: f8f5c0c4-adc9-4c37-be6b-ddc
    16. config:
    17. import:
    18. - optional:nacos:${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #配置中心

    报错问题定位思路

    启动报错:

    Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.

    最开始搜索报错,很多网上说的一般都是忘记加注解@SpringBootApplication,或者没有引入依赖:

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-web</artifactId>
    4. </dependency>

    但是检查并没有遗漏。开始根据问题本身进行定位。

    报错本身就是没有找到ServletWebServerFactory,那么思路就是检查xxxxxxxConfiguration中的代码是否正常执行,这里就是org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration

    因为是Tomcat方式启动所以只需要关心tomcatServletWebServerFactory方法

    这里我设置了debug的方式但是并没有走到这里

    再次全局搜索怀疑可能是自动装配的类org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration有问题

    再次尝试debug发现依然没有走到,继续思考查看类上方相关的Conditional注解条件是否满足,猜测可能是@ConditionalOnWebApplication(type = Type.SERVLET)不满足

    点进注解查看

    继续查看对应的org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition,搜索刚才的相关的SERVLET,继续debug发现type为null直接返回了

    继续查找调用的地方进行debug发现autoConfigurationMetadata传入的就有问题,很多value都是空字符串

    继续定位到上级调用,发现传入的数据依然和上面一样存在问题

    继续跟踪定位,终于调到了我们自己写的代码了

    继续查看上级调用,发现这个类是我们自己拷贝出来的Springboot内部的类,做了一些自定义的改造

    这里就说明,可能是从低版本的Springboot中拷贝出来的,但是升级到2.7.x之后可能存在对应的逻辑变化,所以需要对比一下,大概是哪些代码不一致

    Ctrl+A全选Ctrl+C复制我们自己写的代码,然后跳进内部的AutoConfigurationImportSelector再进行比较

    这里发现我们自己的代码少了一行

    ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);

    根据断言可以知道对应的这段代码不仅是读取了META-INF/spring.factories中的自动装配信息,还读取了META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中的自动装配的bean

    最后查看了包结构,确实如此,升级后META-INF/spring.factories没有了ServletWebServerFactoryAutoConfiguration而是放到了META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中。最后解决就是复制对应的代码到自定义的类中,支持imports中的自动装配

  • 相关阅读:
    vue3源码分析——实现createRenderer,增加runtime-test
    卷妹带你回顾Java基础(一)每日更新Day10
    软件智能:aaas系统的整体构成(草图)
    Xray是什么
    【Java】运算符
    JavaScript 布尔类型(boolean) 和为定义类型(undefined)
    全国计算机三级嵌入式 - 题库 - 真题(含答案) - 未来教育 - 视频讲解 - 资料获取
    美国CN2服务器速度怎么样
    img标签src动态绑定资源失败问题
    基于Python爬虫和K-means算法的校园微博热点话题发现系统
  • 原文地址:https://blog.csdn.net/Box_clf/article/details/133005054