SpringBoot 2.7 to 3.0 アップデートまとめ

SpringBoot 3.0がGAとなりました。
Release Noteを参考に2.7系からの変更点をまとめます。
自分が移行するときに関係のあるものや興味があるものが中心となりますがご容赦ください🙇‍♂️
また、ビルドツールはgradleを前提にまとめます。
mavenユーザの方は、方向性だけ参考にしていただけると幸いです🙇‍♂️

移行方法

メジャーバージョンのアップデートということで、Migration Guideが用意されています。

基本的には以下の記事の共通タスクを実行すれば良いです。

SpringBoot Updateまとめ

これ以外の対応をまとめます。

ひらべー
ひらべー

一部の作業は自動化が可能です!

自動化の方法は以下の記事でまとめているので合わせてご覧ください!

SpringBoot 2.7 to 3.0 自動化(Gradle版)

依存ライブラリのバージョンを確認

SpringBootのバージョンに依存するライブラリを使っている場合、
そのライブラリでSpringBoot3.0に対応したバージョンも確認しておきます。

自分の周りで関係があるものだけ整理しておきます。

ライブラリSpringBoot3.0対応バージョン参考リンク
spring-cloud系2022.0.xhttps://spring.io/projects/spring-cloud
mybatis-spring-boot-starter3.0http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/#requirements

Javaを17以降に更新する

MEMO
すでにJava17以降を利用している場合はこの手順は不要です。

SpringBoot3.0ではJava17以降のバージョンが必要です。

19もサポートされてはいますがLTSなのは17なので、
17に更新をしておくのが無難かと思います。

javax → jakartaへパッケージを変更

javaxパッケージで定義されていたアノテーション(例えば @PostConstructとか@Entityとか@Maxとか)をjakartaパッケージのものに書き換える必要があります。

明示的にjavaxのライブラリを依存に追加していない場合は、コンパイルエラーになるはずなので、気づけます。

注意
javaxのライブラリを明示的に依存に追加している場合は注意が必要です。
普通にアプリケーションは起動するのに実際は期待通りに動いてなんてこともありえます。
// 変更後
import jakarta.annotation.PostConstruct;
// 変更前
// import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class Sample {
    @PostConstruct
    void init() {
        // something to do
    }
}

また、javax系のライブラリを裏で使っているライブラリがないか気になる場合は以下のコマンドで調べることができます。

./gradlew dependencyInsight --dependency javax

共通的に移行が必要な内容は以上です!
ここからは変更点を整理していきます。

ログの日付フォーマット

ログの日付のデフォルトがyyyy-MM-dd HH:mm:ss.SSSからyyyy-MM-dd’T’HH:mm:ss.SSSXXXに変更されました。

logback.xmlや環境変数でフォーマットを指定していない限りこの影響を受けるかと。
特にログをパースして集計するような仕組みを構築している場合、この影響をもろに食らうかもしれません。

環境変数LOG_DATEFORMAT_PATTERNやプロパティlogging.pattern.dateformatyyyy-MM-dd HH:mm:ss.SSSを指定することでこの変更の影響をなくせます。

spring.factoryからEnableAutoConfigurationが廃止

SpringBoot2.7からorg.springframework.boot.autoconfigure.AutoConfiguration.importsでAutoConfigurationクラスを定義できるようになっていたようで、
3.0でそちらを利用する必要があります。以下書き換え例です。

Before

META-INF/spring.factoriesに以下のような記述をしていると思います。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
rhirabay.lib.SampleAutoConfiguration

After

クラス名の部分だけMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsにコピペします。
※複数ある場合は改行で列挙すればOK

rhirabay.lib.SampleAutoConfiguration

URLのマッチング

WebMVC・WebFluxともにURLの最後の/の扱いが変わります。

これまでは/sampleと指定していれば/sample/sample/どちらでもアクセスができましたが、
SpringBoot3.0からは/sampleのみしかアクセスできず、これまでと同じ動作をさせたければ明示的な指定が必要です。

// 変更前
// @GetMapping("/sample")
// 変更後
@GetMapping("/sample", "/sample/")

一括で設定を元に戻したい場合は以下のようなConfigurationクラスを定義すればよいです。

@Configuration
public class WebConfiguration implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setUseTrailingSlashMatch(true);
    }
}

ただ、setUseTrailingSlashMatchが非推奨なメソッドなので互換性を担保したいのであればURLを2つ指定する方針が良いのかなーと

Jettyがサポート外に

もし使用したい場合はServlet APIを5.0にダウングレードする必要があります。
jakarta.servlet.versionを指定すればOKです。

※Release Noteではjakarta-servlet.versionで紹介されていたので今後変わるかも、、、

ext {
  set('jakarta.servlet.version', "5.0")
}

Actuatorの情報をサニタイズ(/env/configprops

Actuatorの/env/configpropsの2つのエンドポイントについて値がマスキングされるようになりました。
これまではパスワード等の機密情報もそのまま表示されてしまっていたのでセキュリティ的に良くなかったものを改善した形です。

もし開発環境だけ値を確認したいとかであれば、management.endpoint.env.show-valuesmanagement.endpoint.configprops.show-valuesALWAYSWHEN_AUTHORIZEDに設定すればよいようです。

メトリクスの収集方法が変更に

メトリクスの収集に関するクラスが調整されています。

http_server_request系のメトリクスのタグの生成ロジックに手を入れていたり、TagProviderとかWebMvcMetricsFilterとかをカスタマイズしている場合は、ServerHttpObservationFilterへの移行が必要なようです。

また、HTTP Client側でspring-boot-actuatorが提供する MetricsWebClientCustomizerMetricsRestTemplateCustomizerを使用している場合は、ObservationWebClientCustomizerObservationRestTemplateCustomizerに切り替える必要があります。

mainクラスの指定方法

これまでbootJarやbootRunでmainクラスを指定していた場合は変更が必要です。

springBoot {
    mainClass = "com.example.Application"
}

RestTemplateで使用するHttpClient

これまでHttpClient4に依存していましたが、HttpClient5への依存に切り替わりました。

使用するHttpClientをカスタイマイズしていた場合、HttpCliet5の利用に切り替える必要があります。

dependencies {
  // 変更前
  // implementation 'org.apache.httpcomponents:httpclient'
  // 変更後
  implementation 'org.apache.httpcomponents.client5:httpclient5'
}

実装の変更点についてはimportするパッケージが変わるのと一部クラスがbuilderパターンで生成することが推奨されているのを把握しておけば良さそうかなと

// httpclient4
// import org.apache.http.client.HttpClient;
// httpclient5
import org.apache.hc.client5.http.classic.HttpClient;
        // PoolingHttpClientConnectionManager
        // httpclient4
        // PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        // connectionManager.setMaxTotal(10);

        // httpclient5(builderパターンで生成)
        PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
                .setMaxConnTotal(10)
                .build();
        // httpclient4
        // SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(SSLContext.getInstance("TLSv1.2"));

        // httpclient5
        SSLConnectionSocketFactory socketFactory = SSLConnectionSocketFactoryBuilder.create()
                .setTlsVersions(TLS.V_1_2)
                .build();

※公式のMigrationGuideはこちらです!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です