SpringBoot2.7升級到3.0的實踐分享

踩刀詩人發表於2023-10-07

背景

最近把專案中的技術框架做一次升級,最重要的就是SpringBoot從2.7.x升級到3.0.x,當然還會有一些周邊的框架也會連帶著升級,比如Mybatis Plus,SpringCloud等,話不多說直接看看有哪些事情要做。

具體事項

主要分兩類,第一類是單純的提升版本,主要如下:

1.jdk升級

SpringBoot3需要jdk17以上,看下官網的介紹。

 

2.構建工具Maven需要升級,3.5+以上。

3.SpringCloud需要升級,原來是2021.0.3,現在決定升級到2022.0.4,中途也嘗試過SpringCloud暫時不升級,但是啟動失敗了,果斷決定升級,二者的對照關係請參考https://start.spring.io/actuator/info。

4.Mybatis,Mybatis-plus需要升級,分別升級到3.5.13,3.5.3.2。

第二類是由於版本升級帶來的一些配置和程式碼的變更,主要如下:

1. javax.需要批次替換

import javax.annotation. 替換為import jakarta.annotation.

import javax.servlet.替換為import jakarta.servlet.

這個我也是有點不解,為什麼連路徑都要做遷移,這個會有一些連帶的改變,比如使用的一些第三方jar使用的是javax.servlet/annotation,那我們就需要找到其高版本看是否切換到了jakarta.servlet/annotation,如果不支援那我們的整體升級可能都要叫停,剛開始也想過找到一些老的jar保證編譯不報錯,但是執行的時候發現根本不行,因為SpringBoot,Spring等在底層使用的時候都切到了jakarta,為了適應新版本框架必須要改,慶幸的是用的第三方jar都有相應的高版本支援。

2.Spring Cloud OpenFeign升級以後,FeignContext不存在

之前有框架程式碼中獲取FeignBean的需求,程式碼如下:

public static <T> T getFeignBean(String beanName, Class<T> tClass) {
      FeignContext feignContext = (FeignContext)getBean("feignContext");
      return feignContext.getInstance(beanName, tClass);
  }

需要調整為FeignClientFactory:

public static <T> T getFeignBean(String beanName, Class<T> tClass) {
    FeignClientFactory feignContext = (FeignClientFactory)getBean("feignContext");
    return feignContext.getInstance(beanName, tClass);
}

3.redis配置修改

之前是spring.redis.xxx,現在需要修改為spring.data.redis.xxx。

4.mybatis plus由3.2.0升級到3.5.3.2以後帶來的幾個調整

4.1 id-type: UUID調整為id-type: ASSIGN_UUID

4.2 攔截器路徑以及構造方式的變化

之前如下:

@Configuration
public class MybatisPlusConfig {
  /**
   * 分頁外掛 
   */
  @Bean
  public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
  }

現在如下:

@Configuration
public class MybatisPlusConfig {
  /**
   * 分頁外掛
   */
  @Bean
  public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
  }

4.3 selectCount返回值由Integer變更為Long

這個好改,直接按照idea的提示改成Math.toIntExact(xxxMapper.selectCount)。

帶來的好處

先說說我最直觀的一個好處,jdk由11升級到17以後空指標的異常提示清晰多了,可以明確的知道是哪個物件空,分別以jdk11和jdk17為例測試一段鏈式呼叫的NPE異常,測試程式碼如下:

static class User{
        int age;
        public int getAge(){
            return age;
        }
}

@Test
public void testNPE(){
    List<User> list = new ArrayList();
    list.add(null);
    list.stream().filter(o -> o.getAge() >9).collect(Collectors.toList())
}

分別看下在jdk11和jdk17下的報錯提示。

jdk11

java.lang.NullPointerException
  at NpeTest.lambda$testNPE$0(NpeTest.java:41)
  at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176)
  at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
  at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
  at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
  at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
  at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
  at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
  at NpeTest.testNPE(NpeTest.java:41)

jdk17

java.lang.NullPointerException: Cannot invoke "NpeTest$User.getAge()" because "o" is null
  at NpeTest.lambda$testNPE$0(NpeTest.java:41)
  at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
  at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
  at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
  at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
  at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
  at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
  at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)

其次就是一次老生常談的好處,比如效能提升,安全加固等,我瞭解的還很淺薄,待我慢慢發掘以後再跟大家分享。

推薦閱讀

https://spring.io/blog/2022/05/24/preparing-for-spring-boot-3-0 

https://docs.spring.io/spring-boot/docs/3.0.10/reference/htmlsingle/#getting-help

https://github.com/spring-projects-experimental/spring-boot-migrator

https://blog.csdn.net/dreamcatcher1314/article/details/131137388

 

 

 

 

相關文章