このセクションでは、Spring Boot を使用するときによく発生するいくつかの一般的な「それを行う方法」の質問に対する回答を提供します。そのカバレッジは網羅的ではありませんが、非常に多くの部分をカバーしています。

ここで取り上げていない特定の問題がある場合は、stackoverflow.com (英語) をチェックして、誰かがすでに回答を提供しているかどうかを確認します。また、新しい質問をするのに最適な場所です(spring-boot タグを使用してください)。

また、このセクションを拡充できることは我々にとっても幸せです。「使い方」を追加する場合は、プルリクエスト (GitHub) を送信してください。

1. Spring Boot アプリケーション

このセクションには、Spring Boot アプリケーションに直接関連するトピックが含まれています。

1.1. 独自の FailureAnalyzer を作成する

FailureAnalyzer(Javadoc) は、起動時に例外をインターセプトし、それを FailureAnalysis(Javadoc) にラップされた人間が読み取れるメッセージに変換する優れた方法です。Spring Boot は、アプリケーションコンテキスト関連の例外、JSR-303 検証などのためのこのようなアナライザーを提供します。独自に作成することもできます。

AbstractFailureAnalyzer は、FailureAnalyzer の便利な拡張機能であり、処理する例外の指定された例外タイプの存在を確認します。それを継承して、実装が例外が実際に存在する場合にのみ例外を処理する機会を得ることができます。何らかの理由で例外を処理できない場合は、null を返して、別の実装に例外を処理する機会を与えます。

FailureAnalyzer 実装は META-INF/spring.factories に登録する必要があります。次の例では、ProjectConstraintViolationFailureAnalyzer を登録します。

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
BeanFactory または Environment にアクセスする必要がある場合、FailureAnalyzer はそれぞれ BeanFactoryAware または EnvironmentAware をそれぞれ実装できます。

1.2. 自動構成のトラブルシューティング

Spring Boot 自動構成は、「正しい動作をする」ために最善を尽くしますが、時には失敗することがあり、その理由を説明するのは難しい場合があります。

Spring Boot ApplicationContext には、本当に便利な ConditionEvaluationReport があります。DEBUG ロギング出力を有効にすると、それを見ることができます。spring-boot-actuator を使用する場合(アクチュエーターの章を参照)、JSON でレポートをレンダリングする conditions エンドポイントもあります。そのエンドポイントを使用してアプリケーションをデバッグし、実行時に Spring Boot によって追加された機能(および追加されていない機能)を確認します。

ソースコードと Javadoc を見ると、さらに多くの質問に答えることができます。コードを読むときは、次の経験則を覚えておいてください。

  • *AutoConfiguration と呼ばれるクラスを探し、そのソースを参照してください。@Conditional* アノテーションに特に注意して、有効にする機能とタイミングを確認してください。コマンドラインまたはシステムプロパティ -Ddebug に --debug を追加して、アプリで行われたすべての自動構成決定のログをコンソールに取得します。アクチュエーターを有効にした実行中のアプリケーションで、同じ情報について conditions エンドポイント(/actuator/conditions または同等の JMX)を調べます。

  • @ConfigurationProperties (ServerProperties (GitHub) など)であるクラスを探し、そこから利用可能な外部構成オプションを読み取ります。@ConfigurationProperties アノテーションには、外部プロパティのプレフィックスとして機能する name 属性があります。ServerProperties には prefix="server" があり、その構成プロパティは server.portserver.address などです。アクチュエーターを有効にした実行中のアプリケーションで、configprops エンドポイントを参照してください。

  • Binder で bind メソッドの使用を探して、緩和された方法で Environment から明示的に構成値をプルします。多くの場合、接頭辞とともに使用されます。

  • Environment に直接バインドする @Value アノテーションを探します。

  • 通常 Environment から解決されたプレースホルダーで評価される SpEL 式にレスポンスして、機能のオンとオフを切り替える @ConditionalOnExpression アノテーションを探します。

1.3. 開始する前に環境または ApplicationContext をカスタマイズする

SpringApplication には、コンテキストまたは環境にカスタマイズを適用するために使用される ApplicationListeners および ApplicationContextInitializers があります。Spring Boot は、META-INF/spring.factories から内部的に使用するために、このようなカスタマイズの多くをロードします。追加のカスタマイズを登録する方法は複数あります。

  • プログラムごとに、アプリケーションごとに、SpringApplication で addListeners および addInitializers メソッドを呼び出してから実行します。

  • 宣言的に、アプリケーションごとに、context.initializer.classes または context.listener.classes プロパティを設定することにより。

  • 宣言的に、すべてのアプリケーションについて、META-INF/spring.factories を追加し、すべてのアプリケーションがライブラリとして使用する jar ファイルをパッケージ化します。

SpringApplication はいくつかの特別な ApplicationEvents をリスナーに送信し(コンテキストが作成される前でも)、ApplicationContext によって公開されたイベントのリスナーも登録します。完全なリストについては、「Spring Boot 機能」セクションの「アプリケーションイベントとリスナー」を参照してください。

EnvironmentPostProcessor を使用して、アプリケーションコンテキストをリフレッシュする前に Environment をカスタマイズすることもできます。次の例に示すように、各実装は META-INF/spring.factories に登録する必要があります。

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

実装は任意のファイルをロードし、Environment に追加できます。たとえば、次の例では、クラスパスから YAML 構成ファイルをロードします。

public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {

    private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Resource path = new ClassPathResource("com/example/myapp/config.yml");
        PropertySource<?> propertySource = loadYaml(path);
        environment.getPropertySources().addLast(propertySource);
    }

    private PropertySource<?> loadYaml(Resource path) {
        if (!path.exists()) {
            throw new IllegalArgumentException("Resource " + path + " does not exist");
        }
        try {
            return this.loader.load("custom-resource", path).get(0);
        }
        catch (IOException ex) {
            throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
        }
    }

}
Environment は、デフォルトで Spring Boot がロードするすべての通常のプロパティソースで既に準備されています。環境からファイルの場所を取得することが可能です。上記の例では、リストの最後に custom-resource プロパティソースを追加して、他の通常の場所のいずれかで定義されたキーが優先されるようにします。カスタム実装では、別の順序を定義できます。
@SpringBootApplication で @PropertySource を使用することは、Environment にカスタムリソースをロードする便利な方法のように思えるかもしれませんが、お勧めしません。このようなプロパティソースは、アプリケーションコンテキストがリフレッシュされるまで Environment に追加されません。これは、リフレッシュが開始される前に読み込まれる logging.* や spring.main.* などの特定のプロパティを構成するには遅すぎます。

1.4. ApplicationContext 階層を構築する (親またはルートコンテキストの追加)

ApplicationBuilder クラスを使用して、親 / 子 ApplicationContext 階層を作成できます。詳細については、「Spring Boot 機能」セクションの「spring-boot-features.html」を参照してください。

1.5. 非 Web アプリケーションを作成する

すべての Spring アプリケーションが Web アプリケーション(または Web サービス)である必要はありません。main メソッドでコードを実行するだけでなく、Spring アプリケーションをブートストラップして、使用するインフラストラクチャをセットアップする場合は、Spring Boot の SpringApplication 機能を使用できます。SpringApplication は、Web アプリケーションが必要かどうかに応じて、ApplicationContext クラスを変更します。これを支援するために最初にできることは、サーバー関連の依存関係(サーブレット API など)をクラスパスから除外することです。それができない場合(たとえば、同じコードベースから 2 つのアプリケーションを実行する場合)、SpringApplication インスタンスで setWebApplicationType(WebApplicationType.NONE) を明示的に呼び出すか、applicationContextClass プロパティを設定できます(Java API または外部プロパティを使用)。ビジネスロジックとして実行するアプリケーションコードは、CommandLineRunner として実装し、@Bean 定義としてコンテキストにドロップできます。

2. プロパティと構成

このセクションには、プロパティおよび構成設定の設定と読み取り、および Spring Boot アプリケーションとの相互作用に関するトピックが含まれています。

2.1. ビルド時にプロパティを自動的に展開

プロジェクトのビルド構成でも指定されている一部のプロパティをハードコードするのではなく、既存のビルド構成を代わりに使用して自動的に展開できます。これは、Maven と Gradle の両方で可能です。

2.1.1. Maven を使用した自動プロパティ拡張

リソースフィルタリングを使用して、Maven プロジェクトのプロパティを自動的に展開できます。spring-boot-starter-parent を使用する場合、次の例に示すように、@[email protected] (英語)  プレースホルダーで Maven の「プロジェクトプロパティ」を参照できます。

そのようにフィルタリングされるのは本番構成のみです(言い換えると、src/test/resources にはフィルタリングは適用されません)。
addResources フラグを有効にすると、spring-boot:run ゴールは src/main/resources をクラスパスに直接追加できます(ホットリロードの目的で)。そうすると、リソースのフィルタリングとこの機能が回避されます。代わりに、exec:java ゴールを使用するか、プラグインの構成をカスタマイズできます。詳細については、プラグインの使用方法のページを参照してください。

スターターの親を使用しない場合は、pom.xml の <build/> 要素内に次の要素を含める必要があります。

<resources>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
    </resource>
</resources>

また、<plugins/> 内に次の要素を含める必要があります。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.7</version>
    <configuration>
        <delimiters>
            <delimiter>@</delimiter>
        </delimiters>
        <useDefaultDelimiters>false</useDefaultDelimiters>
    </configuration>
</plugin>
構成で標準 Spring プレースホルダー(${placeholder} など)を使用する場合、useDefaultDelimiters プロパティは重要です。そのプロパティが false に設定されていない場合、これらはビルドによって拡張される可能性があります。

2.1.2. Gradle を使用した自動プロパティ拡張

次の例に示すように、Java プラグインの processResources タスクを構成することにより、Gradle プロジェクトからプロパティを自動的に展開できます。

processResources {
    expand(project.properties)
}

その後、次の例に示すように、プレースホルダーを使用して Gradle プロジェクトのプロパティを参照できます。

app.name=${name}
app.description=${description}
Gradle の expand メソッドは、Groovy の SimpleTemplateEngine を使用して、${..} トークンを変換します。${..} スタイルは、Spring 独自のプロパティプレースホルダーメカニズムと競合します。Spring プロパティプレースホルダーと自動展開を併用するには、Spring プロパティプレースホルダーを次のようにエスケープします: \${..}

2.2. SpringApplication の構成の外部化

SpringApplication には Bean プロパティ(主に setter)があるため、アプリケーションを作成するときに Java API を使用して動作を変更できます。または、spring.main.* でプロパティを設定することにより、構成を外部化できます。例: application.properties では、次の設定があります。

spring.main.web-application-type=none
spring.main.banner-mode=off

その場合、起動時に Spring Boot バナーは出力されず、アプリケーションは組み込み Web サーバーを起動しません。

外部構成で定義されたプロパティは、ApplicationContext の作成に使用されるソースの顕著な例外を除き、Java API で指定された値をオーバーライドします。次のアプリケーションを検討してください。

new SpringApplicationBuilder()
    .bannerMode(Banner.Mode.OFF)
    .sources(demo.MyApp.class)
    .run(args);

次に、次の構成を検討します。

spring.main.sources=com.acme.Config,com.acme.ExtraConfig
spring.main.banner-mode=console

実際のアプリケーション(構成によって上書きされるように)バナーを示し、(次の順序で) ApplicationContext ための 3 つのソースを使用: demo.MyAppcom.acme.Config、及び com.acme.ExtraConfig

2.3. アプリケーションの外部プロパティの場所を変更する

デフォルトでは、異なるソースのプロパティが定義済みの順序で Spring Environment に追加されます(正確な順序については、「Spring Boot 機能」セクションの「spring-boot-features.html」を参照してください)。

次のシステムプロパティ(または環境変数)を指定して、動作を変更することもできます。

  • spring.config.name (SPRING_CONFIG_NAME): ファイル名のルートとしてのデフォルトは application です。

  • spring.config.location (SPRING_CONFIG_LOCATION): ロードするファイル(クラスパスリソースや URL など)。このドキュメントには別の Environment プロパティソースが設定されており、システムプロパティ、環境変数、またはコマンドラインによってオーバーライドできます。

環境の設定に関係なく、Spring Boot は上記のように application.properties を常にロードします。デフォルトでは、YAML が使用されている場合、「.yml」拡張子を持つファイルもリストに追加されます。

Spring Boot は、DEBUG レベルでロードされた構成ファイルと、TRACE レベルで見つからなかった候補をログに記録します。

詳細については、ConfigFileApplicationListener (GitHub) を参照してください。

2.4. 「短い」コマンドライン引数を使用する

コマンドラインで設定プロパティを設定するために、--server.port=9000 の代わりに --port=9000 を使用したい人もいます。次の例に示すように、application.properties のプレースホルダーを使用して、この動作を有効にできます。

server.port=${port:8080}
spring-boot-starter-parent POM から継承する場合、maven-resources-plugins のデフォルトのフィルタートークンは ${*} から @ (つまり、${maven.token} ではなく @[email protected] (英語) )に変更され、Spring スタイルのプレースホルダーとの競合を防ぎます。application.properties の Maven フィルタリングを直接有効にしている場合は、デフォルトのフィルタートークンを変更して、他の区切り文字 (Apache) を使用することもできます。
この特定のケースでは、ポートバインディングは Heroku や Cloud Foundry などの PaaS 環境で機能します。これら 2 つのプラットフォームでは、PORT 環境変数が自動的に設定され、Spring は Environment プロパティの大文字のシノニムにバインドできます。

2.5. 外部プロパティに YAML を使用する

YAML は JSON のスーパーセットであるため、次の例に示すように、外部プロパティを階層形式で保存するための便利な構文です。

spring:
    application:
        name: cruncher
    datasource:
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost/test
server:
    port: 9000

application.yml というファイルを作成し、クラスパスのルートに配置します。次に、snakeyaml を依存関係に追加します(Maven は org.yaml:snakeyaml を調整します。spring-boot-starter を使用する場合は既に含まれています)。YAML ファイルは Java Map<String,Object> (JSON オブジェクトのように)に解析され、Spring Boot はマップをフラット化して、Java の Properties ファイルで多くの人が慣れているように、1 レベルの深さでピリオドで区切られたキーを持つようにします。

前述の YAML の例は、次の application.properties ファイルに対応しています。

spring.application.name=cruncher
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000

YAML の詳細については、「Spring Boot 機能」セクションの「spring-boot-features.html」を参照してください。

2.6. アクティブ Spring プロファイルを設定する

Spring Environment にはこのための API がありますが、通常はシステムプロパティ(spring.profiles.active)または OS 環境変数(SPRING_PROFILES_ACTIVE)を設定します。また、次のように、-D 引数を使用してアプリケーションを起動できます(メインクラスまたは jar アーカイブの前に配置することを忘れないでください)。

$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar

Spring Boot では、次の例に示すように、application.properties でアクティブなプロファイルを設定することもできます。

spring.profiles.active=production

この方法で設定された値は、SpringApplicationBuilder.profiles() メソッドではなく、システムプロパティまたは環境変数の設定に置き換えられます。後者の Java API を使用して、デフォルトを変更せずにプロファイルを拡張できます。

詳細については、「Spring Boot 機能」セクションの「spring-boot-features.html」を参照してください。

2.7. 環境に応じて構成を変更する

YAML ファイルは、実際には --- 行で区切られた一連のドキュメントであり、各ドキュメントは個別にフラット化されたマップに解析されます。

YAML ドキュメントに spring.profiles キーが含まれている場合、プロファイル値(プロファイルのコンマ区切りリスト)が Spring Environment.acceptsProfiles() メソッドに送られます。これらのプロファイルのいずれかがアクティブな場合、次の例に示すように、そのドキュメントは最終的なマージに含まれます(そうでない場合は含まれません)。

server:
    port: 9000
---

spring:
    profiles: development
server:
    port: 9001

---

spring:
    profiles: production
server:
    port: 0

上記の例では、デフォルトのポートは 9000 です。ただし、「開発」という Spring プロファイルがアクティブな場合、ポートは 9001 です。「本番」がアクティブな場合、ポートは 0 です。

YAML ドキュメントは、検出された順にマージされます。後の値は前の値を上書きします。

プロパティファイルで同じことを行うには、application-${profile}.properties を使用してプロファイル固有の値を指定できます。

2.8. 外部プロパティの組み込みオプションを理解する

Spring Boot は、実行時に application.properties (または .yml ファイルおよびその他の場所)から外部プロパティをアプリケーションにバインドします。1 つの場所にすべてのサポートされているプロパティの完全なリストはありません(技術的にはできません)。これは、クラスパス上の追加の jar ファイルから提供される可能性があるためです。

アクチュエーター機能を備えた実行中のアプリケーションには、configprops エンドポイントがあり、@ConfigurationProperties を介して使用可能なすべてのバインド済みプロパティとバインド可能プロパティが表示されます。

付録には、Spring Boot でサポートされる最も一般的なプロパティのリストを含む application.properties の例が含まれています。最終的なリストは、@ConfigurationProperties および @Value アノテーションのソースコードを検索することと、Binder をときどき使用することから得られます。読み込みプロパティの正確な順序の詳細については、「spring-boot-features.html」を参照してください。

3. 組み込み Web サーバー

各 Spring Boot Web アプリケーションには、組み込み Web サーバーが含まれています。この機能は、組み込みサーバーの変更方法や組み込みサーバーの構成方法など、多くの使い方の質問につながります。このセクションでは、これらの質問に回答します。

3.1. 別の Web サーバーを使用する

多くの Spring Boot スターターには、デフォルトの組み込みコンテナーが含まれています。

  • サーブレットスタックアプリケーションの場合、spring-boot-starter-web には spring-boot-starter-tomcat を含めることで Tomcat が含まれますが、代わりに spring-boot-starter-jetty または spring-boot-starter-undertow を使用できます。

  • リアクティブスタックアプリケーションの場合、spring-boot-starter-webflux には spring-boot-starter-reactor-netty を含めることにより Reactor Netty が含まれますが、代わりに spring-boot-starter-tomcatspring-boot-starter-jetty または spring-boot-starter-undertow を使用できます。

別の HTTP サーバーに切り替える場合、必要な依存関係を含めることに加えて、デフォルトの依存関係を除外する必要があります。Spring Boot は、HTTP サーバー用に個別のスターターを提供し、このプロセスを可能な限り簡単にします。

次の Maven の例は、Tomcat を除外し、Spring MVC に Jetty を含める方法を示しています。

<properties>
    <servlet-api.version>3.1.0</servlet-api.version>
</properties>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <!-- Exclude the Tomcat dependency -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Tomcat 9 や Undertow 2.0 とは異なり、Jetty 9.4 は Servlet 4.0. をサポートしていないため、サーブレット API のバージョンはオーバーライドされています。

次の Gradle の例は、Netty を除外し、Spring WebFlux の Undertow を含める方法を示しています。

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-webflux') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-reactor-netty'
    }
    // Use Undertow instead
    implementation 'org.springframework.boot:spring-boot-starter-undertow'
    // ...
}
WebClient クラスを使用するには spring-boot-starter-reactor-netty が必要なので、別の HTTP サーバーを含める必要がある場合でも、Netty への依存関係を維持する必要があります。

3.2. Web サーバーの無効化

クラスパスに Web サーバーの起動に必要なビットが含まれている場合、Spring Boot は自動的に起動します。この動作を無効にするには、次の例に示すように、application.properties で WebApplicationType を構成します。

spring.main.web-application-type=none

3.3. HTTP ポートを変更する

スタンドアロンアプリケーションでは、メイン HTTP ポートはデフォルトで 8080 になりますが、server.port で設定できます(たとえば、application.properties またはシステムプロパティとして)。Environment 値の緩いバインディングのおかげで、SERVER_PORT を使用することもできます(たとえば、OS 環境変数として)。

HTTP エンドポイントを完全にオフにしながら WebApplicationContext を作成するには、server.port=-1 を使用します(そうすることはテストに役立つことがあります)。

詳細については、「Spring Boot 機能」セクションの「spring-boot-features.html」、または ServerProperties (GitHub) ソースコードを参照してください。

3.4. ランダムな未割り当ての HTTP ポートを使用する

(衝突を防ぐために OS ネイティブを使用して)空きポートをスキャンするには、server.port=0 を使用します。

3.5. 実行時に HTTP ポートを発見する

サーバーが実行されているポートには、ログ出力または ServletWebServerApplicationContext から WebServer を介してアクセスできます。それを取得し、初期化されていることを確認する最善の方法は、タイプ ApplicationListener<ServletWebServerInitializedEvent> の @Bean を追加し、発行時にイベントからコンテナーをプルすることです。

次の例に示すように、@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) を使用するテストでは、@LocalServerPort アノテーションを使用して、実際のポートをフィールドに挿入することもできます。

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {

    @Autowired
    ServletWebServerApplicationContext server;

    @LocalServerPort
    int port;

    // ...

}

@LocalServerPort は @Value("${local.server.port}") のメタアノテーションです。通常のアプリケーションでポートを挿入しようとしないでください。先ほど見たように、値はコンテナーが初期化された後にのみ設定されます。テストとは異なり、アプリケーションコードのコールバックは早期に(値が実際に利用可能になる前に)処理されます。

3.6. HTTP レスポンス圧縮を有効にする

HTTP レスポンス圧縮は、Jetty、Tomcat、Undertow でサポートされています。次のように、application.properties で有効にできます。

server.compression.enabled=true

デフォルトでは、圧縮を実行するには、レスポンスの長さが少なくとも 2048 バイトである必要があります。server.compression.min-response-size プロパティを設定することにより、この動作を構成できます。

デフォルトでは、コンテンツタイプが次のいずれかである場合にのみ、レスポンスが圧縮されます。

  • text/html

  • text/xml

  • text/plain

  • text/css

  • text/javascript

  • application/javascript

  • application/json

  • application/xml

server.compression.mime-types プロパティを設定することにより、この動作を構成できます。

3.7. SSL を構成する

SSL は、通常 application.properties または application.yml でさまざまな server.ssl.* プロパティを設定することにより、宣言的に構成できます。次の例は、application.properties での SSL プロパティの設定を示しています。

server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret

サポートされているすべてのプロパティの詳細については、Ssl (GitHub) を参照してください。

上記の例のような構成を使用すると、アプリケーションはポート 8080 でプレーン HTTP コネクターをサポートしなくなります。Spring Boot は、application.properties を介した HTTP コネクターと HTTPS コネクターの両方の構成をサポートしません。両方が必要な場合は、どちらかをプログラムで設定する必要があります。HTTP コネクターはプログラムで簡単に構成できるため、application.properties を使用して HTTPS を構成することをお勧めします。

3.8. HTTP/2 を構成する

server.http2.enabled 構成プロパティを使用して、Spring Boot アプリケーションで HTTP/2 サポートを有効にできます。このサポートは、選択された Web サーバーとアプリケーション環境に依存します。JDK8 では、このプロトコルはすぐにサポートされないためです。

Spring Boot は、HTTP/2 プロトコルのクリアテキストバージョンである h2c をサポートしていません。最初に SSL を構成する必要があります。

3.8.1. Undertow を使用した HTTP/2

Undertow 1.4.0 + 以降、JDK8 で追加要件なしに HTTP/2 がサポートされます。

3.8.2. Jetty を使用した HTTP/2

Jetty 9.4.8, 以降、HTTP/2 は暗号化ライブラリ (英語) でもサポートされます。このサポートを有効にするには、アプリケーションに org.eclipse.jetty:jetty-alpn-conscrypt-server および org.eclipse.jetty.http2:http2-server の 2 つの追加の依存関係が必要です。

3.8.3. Tomcat を使用した HTTP/2

Spring Boot はデフォルトで Tomcat 9.0.x に同梱されており、JDK 9 以降を使用している場合はそのままで HTTP/2 をサポートしています。または、libtcnative ライブラリとその依存関係がホストオペレーティングシステムにインストールされている場合、JDK 8 で HTTP/2 を使用できます。

ライブラリディレクトリは、JVM ライブラリパスで使用できるようにする必要があります(まだ使用していない場合)。-Djava.library.path=/usr/local/opt/tomcat-native/lib などの JVM 引数を使用してこれを行うことができます。詳細については、Tomcat の公式ドキュメントを参照してください (Apache)

そのネイティブサポートなしで JDK 8 で Tomcat 9.0.x を起動すると、次のエラーが記録されます。

ERROR 8787 --- [           main] o.a.coyote.http11.Http11NioProtocol      : The upgrade handler [org.apache.coyote.http2.Http2Protocol] for [h2] only supports upgrade via ALPN but has been configured for the ["https-jsse-nio-8443"] connector that does not support ALPN.

このエラーは致命的ではなく、アプリケーションは引き続き HTTP/1.1 SSL サポートで開始されます。

3.8.4. Reactor Netty を使用した HTTP/2

spring-boot-webflux-starter は、デフォルトで Reactor Netty をサーバーとして使用しています。Reactor Netty は、JDK 9 以降の JDK サポートを使用して HTTP/2 用に構成できます。JDK 8 環境の場合、または最適な実行時パフォーマンスのために、このサーバーはネイティブライブラリで HTTP/2 もサポートします。それを可能にするには、アプリケーションに追加の依存関係が必要です。

Spring Boot は、すべてのプラットフォームのネイティブライブラリを含む io.netty:netty-tcnative-boringssl-static "uber jar" のバージョンを管理します。開発者は、分類子を使用して必要な依存関係のみをインポートすることを選択できます(Netty 公式ドキュメント (英語) を参照)。

3.9. Web サーバーを構成する

一般に、まず多くの利用可能な構成キーのいずれかを使用することを検討し、application.properties (または application.yml または環境など。「外部プロパティの組み込みオプションを理解する」を参照)に新しいエントリを追加して Web サーバーをカスタマイズします。server.* 名前空間はここでは非常に便利で、サーバー固有の機能のために server.tomcat.*server.jetty.* などの名前空間が含まれています。appendix-application-properties.html のリストを参照してください。

前のセクションでは、圧縮、SSL、HTTP/2 など、すでに多くの一般的なユースケースについて説明しました。ただし、ユースケースに設定キーが存在しない場合は、WebServerFactoryCustomizer(Javadoc) を確認する必要があります。このようなコンポーネントを宣言し、選択に関連するサーバーファクトリにアクセスできます。選択したサーバー(Tomcat、Jetty、Reactor、Netty、Undertow)および選択した Web スタック(サーブレットまたはリアクティブ)のバリアントを選択する必要があります。

以下の例は、spring-boot-starter-web (サーブレットスタック)を使用した Tomcat の場合です。

@Component
public class MyTomcatWebServerCustomizer
        implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        // customize the factory here
    }
}

さらに、Spring Boot は以下を提供します。

サーバー サーブレットスタック リアクティブスタック

Tomcat

TomcatServletWebServerFactory

TomcatReactiveWebServerFactory

Jetty

JettyServletWebServerFactory

JettyReactiveWebServerFactory

Undertow

UndertowServletWebServerFactory

UndertowReactiveWebServerFactory

Reactor

なし

NettyReactiveWebServerFactory

WebServerFactory にアクセスしたら、多くの場合、カスタマイザーを追加して、コネクター、サーバーリソース、サーバー自体などの特定の部分を構成できます。すべてサーバー固有の API を使用します。

最後の手段として、独自の WebServerFactory コンポーネントを宣言することもできます。これは、Spring Boot によって提供されるコンポーネントをオーバーライドします。この場合、server 名前空間の構成プロパティに依存することはできなくなります。

3.10. サーブレット、フィルター、またはリスナーをアプリケーションに追加する

サーブレットスタックアプリケーション、つまり spring-boot-starter-web を使用する場合、ServletFilterServletContextListener と、サーブレット API でサポートされる他のリスナーをアプリケーションに追加するには、2 つの方法があります。

3.10.1. Spring Bean を使用して、サーブレット、フィルター、またはリスナーを追加する

Spring Bean を使用して ServletFilter またはサーブレット *Listener を追加するには、@Bean 定義を提供する必要があります。これは、構成または依存関係を注入する場合に非常に役立ちます。ただし、アプリケーションライフサイクルの非常に早い段階でコンテナーにインストールする必要があるため、他の Bean の初期化が頻繁に行われないように注意する必要があります。(例: DataSource または JPA 構成に依存させるのは得策ではありません)初期化ではなく、最初に使用したときに遅延して Bean を初期化することにより、このような制限を回避できます。

Filters および Servlets の場合、基礎となるコンポーネントの代わりに、またはそれに加えて、FilterRegistrationBean または ServletRegistrationBean を追加することにより、マッピングおよび初期化パラメーターを追加することもできます。

フィルター登録で dispatcherType が指定されていない場合、REQUEST が使用されます。これは、サーブレット仕様のデフォルトのディスパッチャータイプと一致します。

他の Spring Bean と同様に、サーブレットフィルター Bean の順序を定義できます。「spring-boot-features.html」セクションを必ず確認してください。

サーブレットまたはフィルターの登録を無効にする

前述のように、Servlet または Filter Bean は、サーブレットコンテナーに自動的に登録されます。特定の Filter または Servlet Bean の登録を無効にするには、次の例に示すように、登録 Bean を作成し、無効としてマークします。

@Bean
public FilterRegistrationBean registration(MyFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}

3.10.2. クラスパススキャンを使用してサーブレット、フィルター、リスナーを追加する

@WebServlet@WebFilter、および @WebListener アノテーション付きクラスは、@Configuration クラスに @ServletComponentScan アノテーションを付け、登録するコンポーネントを含むパッケージを指定することにより、組み込みサーブレットコンテナーに自動的に登録できます。デフォルトでは、@ServletComponentScan はアノテーション付きクラスのパッケージからスキャンします。

3.11. アクセスログを構成する

Tomcat、Undertow、および Jetty のアクセスログは、それぞれのネームスペースを使用して構成できます。

たとえば、次の設定は、カスタムパターン (Apache) で Tomcat へのアクセスを記録します。

server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
ログのデフォルトの場所は、Tomcat ベースディレクトリに相対的な logs ディレクトリです。デフォルトでは、logs ディレクトリは一時ディレクトリです。そのため、Tomcat のベースディレクトリを修正するか、ログに絶対パスを使用することができます。上記の例では、ログはアプリケーションの作業ディレクトリに関連する my-tomcat/logs で利用可能です。

Undertow のアクセスロギングは、次の例に示すように、同様の方法で構成できます。

server.undertow.accesslog.enabled=true
server.undertow.accesslog.pattern=%t %a "%r" %s (%D ms)

ログは、アプリケーションの作業ディレクトリに相対的な logs ディレクトリに保存されます。server.undertow.accesslog.dir プロパティを設定することにより、この場所をカスタマイズできます。

最後に、Jetty のアクセスロギングは次のように構成することもできます。

server.jetty.accesslog.enabled=true
server.jetty.accesslog.filename=/var/log/jetty-access.log

デフォルトでは、ログは System.err にリダイレクトされます。詳細については、Jetty のドキュメント (英語) を参照してください。

3.12. フロントエンドプロキシサーバーの背後で実行する

アプリケーションがプロキシ、ロードバランサー、またはクラウド内で実行されている場合、リクエスト情報(ホスト、ポート、スキームなど)は途中で変更される可能性があります。アプリケーションは 10.10.10.10:8080 で実行されている可能性がありますが、HTTP クライアントは example.org のみを見るはずです。

RFC7239「転送ヘッダー」 (英語) は、Forwarded HTTP ヘッダーを定義します。プロキシはこのヘッダーを使用して、元のリクエストに関する情報を提供できます。これらのヘッダーを読み取るようにアプリケーションを設定し、リンクを作成して HTTP 302 レスポンス、JSON ドキュメント、または HTML ページでクライアントに送信するときにその情報を自動的に使用できます。X-Forwarded-HostX-Forwarded-PortX-Forwarded-ProtoX-Forwarded-Ssl や X-Forwarded-Prefix などの非標準ヘッダーもあります。

プロキシが一般的に使用される X-Forwarded-For および X-Forwarded-Proto ヘッダーを追加する場合、server.forward-headers-strategy を NATIVE に設定するだけでサポートできます。このオプションを使用すると、Web サーバー自体がこの機能をネイティブでサポートします。特定のドキュメントを確認して、特定の動作について学ぶことができます。

これで十分でない場合、Spring Framework は ForwardedHeaderFilter を提供します。server.forward-headers-strategy を FRAMEWORK に設定することにより、アプリケーションでサーブレットフィルターとして登録できます。

アプリケーションが Cloud Foundry または Heroku で実行されている場合、server.forward-headers-strategy プロパティはデフォルトで NATIVE になります。他のすべてのインスタンスでは、デフォルトで NONE になります。

3.12.1. Tomcat のプロキシ設定をカスタマイズする

Tomcat を使用する場合は、次の例に示すように、「転送された」情報を伝達するために使用されるヘッダーの名前を追加で構成できます。

server.tomcat.remoteip.remote-ip-header=x-your-remote-ip-header
server.tomcat.remoteip.protocol-header=x-your-protocol-header

Tomcat は、信頼される内部プロキシに一致するデフォルトの正規表現を使用して構成されます。デフォルトでは、10/8192.168/16169.254/16 および 127/8 の IP アドレスは信頼されています。次の例に示すように、application.properties にエントリを追加することにより、バルブの構成をカスタマイズできます。

server.tomcat.remoteip.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
二重バックスラッシュは、構成にプロパティファイルを使用する場合にのみ必要です。YAML を使用する場合、単一のバックスラッシュで十分であり、前の例に示されている値と同等の値は 192\.168\.\d{1,3}\.\d{1,3} になります。
internal-proxies を空に設定することにより、すべてのプロキシを信頼できます(ただし、運用環境ではそうしないでください)。

Tomcat の RemoteIpValve の設定を完全に制御するには、自動構成をオフにし(そうするために server.forward-headers-strategy=NONE を設定します)、TomcatServletWebServerFactory Bean に新しいバルブインスタンスを追加します。

3.13. Tomcat で複数のコネクターを有効にする

次の例に示すように、org.apache.catalina.connector.Connector を TomcatServletWebServerFactory に追加して、HTTP および HTTPS コネクターを含む複数のコネクターを許可できます。

@Bean
public ServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    tomcat.addAdditionalTomcatConnectors(createSslConnector());
    return tomcat;
}

private Connector createSslConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
    try {
        File keystore = new ClassPathResource("keystore").getFile();
        File truststore = new ClassPathResource("keystore").getFile();
        connector.setScheme("https");
        connector.setSecure(true);
        connector.setPort(8443);
        protocol.setSSLEnabled(true);
        protocol.setKeystoreFile(keystore.getAbsolutePath());
        protocol.setKeystorePass("changeit");
        protocol.setTruststoreFile(truststore.getAbsolutePath());
        protocol.setTruststorePass("changeit");
        protocol.setKeyAlias("apitester");
        return connector;
    }
    catch (IOException ex) {
        throw new IllegalStateException("can't access keystore: [" + keystore
                + "] or truststore: [" + truststore + "]", ex);
    }
}

3.14. Tomcat の LegacyCookieProcessor を使用する

デフォルトでは、Spring Boot で使用される組み込み Tomcat は Cookie 形式の「バージョン 0」をサポートしていないため、次のエラーが表示される場合があります。

java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value

可能な限り、後の Cookie 仕様に準拠した値のみを保存するようにコードを更新することを検討してください。ただし、Cookie の作成方法を変更できない場合は、代わりに LegacyCookieProcessor を使用するように Tomcat を構成できます。LegacyCookieProcessor に切り替えるには、次の例に示すように、TomcatContextCustomizer を追加する WebServerFactoryCustomizer Bean を使用します。

@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
    return (factory) -> factory
            .addContextCustomizers((context) -> context.setCookieProcessor(new LegacyCookieProcessor()));
}

3.15. Tomcat の MBean レジストリを有効にする

組み込み Tomcat の MBean レジストリはデフォルトで無効になっています。これにより、Tomcat のメモリフットプリントが最小限に抑えられます。Tomcat の MBean を使用して、たとえば、Micrometer を介してメトリックを公開できるようにする場合は、次の例に示すように、server.tomcat.mbeanregistry.enabled プロパティを使用する必要があります。

server.tomcat.mbeanregistry.enabled=true

3.16. Undertow で複数のリスナーを有効にする

次の例に示すように、UndertowBuilderCustomizer を UndertowServletWebServerFactory に追加し、リスナーを Builder に追加します。

@Bean
public UndertowServletWebServerFactory servletWebServerFactory() {
    UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
    factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {

        @Override
        public void customize(Builder builder) {
            builder.addHttpListener(8080, "0.0.0.0");
        }

    });
    return factory;
}

3.17. @ServerEndpoint を使用して WebSocket エンドポイントを作成する

埋め込みコンテナーを使用した Spring Boot アプリケーションで @ServerEndpoint を使用する場合は、次の例に示すように、単一の ServerEndpointExporter@Bean を宣言する必要があります。

@Bean
public ServerEndpointExporter serverEndpointExporter() {
    return new ServerEndpointExporter();
}

前の例に示されている Bean は、@ServerEndpoint アノテーション付き Bean を基礎となる WebSocket コンテナーに登録します。スタンドアロンサーブレットコンテナーにデプロイされる場合、このロールはサーブレットコンテナー初期化子によって実行され、ServerEndpointExporter Bean は必要ありません。

4. Spring MVC

Spring Boot には、Spring MVC を含む多くのスターターがあります。一部のスターターには、Spring MVC に直接依存するのではなく、Spring MVC に依存することに注意してください。このセクションでは、Spring MVC および Spring Boot に関する一般的な質問に回答します。

4.1. JSON REST サービスを作成する

次の例に示すように、Spring Boot アプリケーションの Spring @RestController は、Jackson2 がクラスパス上にある限り、デフォルトで JSON レスポンスをレンダリングする必要があります。

@RestController
public class MyController {

    @RequestMapping("/thing")
    public MyThing thing() {
            return new MyThing();
    }

}

Jackson2 が MyThing を直列化できる限り(通常の POJO または Groovy オブジェクトの場合は true)、localhost:8080/thing はデフォルトで JSON 表現を提供します。ブラウザは XML を好む Accept ヘッダーを送信する傾向があるため、ブラウザでは XML レスポンスが表示されることがあります。

4.2. XML REST サービスを作成する

クラスパスに Jackson XML 拡張(jackson-dataformat-xml)がある場合、それを使用して XML レスポンスをレンダリングできます。JSON に使用した前の例は機能します。Jackson XML レンダラーを使用するには、次の依存関係をプロジェクトに追加します。

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

Jackson の XML 拡張機能が利用できず、JAXB が利用可能な場合、次の例に示すように、MyThing に @XmlRootElement としてアノテーションを付けるという追加要件を使用して XML をレンダリングできます。

@XmlRootElement
public class MyThing {
    private String name;
    // .. getters and setters
}

JAXB は、Java 8 でそのまま使用できる場合にのみ使用できます。最新の Java 世代を使用している場合は、プロジェクトに次の依存関係を追加します。

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
</dependency>
サーバーに JSON ではなく XML をレンダリングさせるには、Accept: text/xml ヘッダーを送信する(またはブラウザーを使用する)必要があります。

4.3. Jackson ObjectMapper をカスタマイズする

Spring MVC(クライアントおよびサーバー側)は、HttpMessageConverters を使用して、HTTP 交換でのコンテンツ変換をネゴシエートします。Jackson がクラスパス上にある場合、Jackson2ObjectMapperBuilder が提供するデフォルトのコンバーターをすでに取得しています。そのインスタンスは自動的に構成されます。

ObjectMapper (または Jackson XML コンバーターの場合は XmlMapper)インスタンス(デフォルトで作成)には、以下のカスタマイズされたプロパティがあります。

  • MapperFeature.DEFAULT_VIEW_INCLUSION は無効です

  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES は無効です

  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS は無効です

Spring Boot には、この動作を簡単にカスタマイズできるいくつかの機能もあります。

環境を使用して、ObjectMapper および XmlMapper インスタンスを構成できます。Jackson は、処理のさまざまなアスペクトを構成するために使用できる、単純なオン / オフ機能の広範なスイートを提供します。これらの機能は、環境内のプロパティにマッピングされる 6 つの列挙(Jackson)で説明されています。

列挙型 プロパティ

com.fasterxml.jackson.databind.DeserializationFeature

spring.jackson.deserialization.<feature_name>

truefalse

com.fasterxml.jackson.core.JsonGenerator.Feature

spring.jackson.generator.<feature_name>

truefalse

com.fasterxml.jackson.databind.MapperFeature

spring.jackson.mapper.<feature_name>

truefalse

com.fasterxml.jackson.core.JsonParser.Feature

spring.jackson.parser.<feature_name>

truefalse

com.fasterxml.jackson.databind.SerializationFeature

spring.jackson.serialization.<feature_name>

truefalse

com.fasterxml.jackson.annotation.JsonInclude.Include

spring.jackson.default-property-inclusion

alwaysnon_nullnon_absentnon_defaultnon_empty

例:プリティプリントを有効にするには、spring.jackson.serialization.indent_output=true を設定します。緩いバインディングの使用のおかげで、indent_output のケースは対応する列挙定数のケースと一致する必要がないことに注意してください。これは INDENT_OUTPUT です。

この環境ベースの構成は、自動構成された Jackson2ObjectMapperBuilder Bean に適用され、自動構成された ObjectMapper Bean を含む、ビルダーを使用して作成されたすべてのマッパーに適用されます。

コンテキストの Jackson2ObjectMapperBuilder は、1 つ以上の Jackson2ObjectMapperBuilderCustomizer Bean によってカスタマイズできます。このようなカスタマイザー Bean は並べ替えることができ(ブートのカスタマイザーの順序は 0)、ブートのカスタマイズの前後に追加のカスタマイズを適用できます。

タイプ com.fasterxml.jackson.databind.Module の Bean はすべて、自動構成された Jackson2ObjectMapperBuilder に自動的に登録され、作成する ObjectMapper インスタンスに適用されます。これにより、アプリケーションに新しい機能を追加するときにカスタムモジュールを提供するグローバルメカニズムが提供されます。

デフォルトの ObjectMapper を完全に置き換える場合は、そのタイプの @Bean を定義して @Primary としてマークするか、ビルダーベースのアプローチを好む場合は Jackson2ObjectMapperBuilder@Bean を定義します。どちらの場合でも、そうすると ObjectMapper のすべての自動構成が無効になることに注意してください。

タイプ MappingJackson2HttpMessageConverter の @Beans を指定すると、MVC 構成のデフォルト値が置き換えられます。また、タイプ HttpMessageConverters の便利な Bean が提供されます(デフォルトの MVC 構成を使用する場合は常に利用可能です)。デフォルトおよびユーザー拡張のメッセージコンバーターにアクセスするための便利な方法がいくつかあります。

詳細については、「@ResponseBody レンダリングのカスタマイズ」セクションおよび WebMvcAutoConfiguration (GitHub) ソースコードを参照してください。

4.4. @ResponseBody レンダリングのカスタマイズ

Spring は HttpMessageConverters を使用して @ResponseBody (または @RestController からのレスポンス)をレンダリングします。Spring Boot コンテキストに適切なタイプの Bean を追加することにより、追加のコンバーターを提供できます。追加する Bean が、デフォルトで含まれるタイプ(JSON 変換の MappingJackson2HttpMessageConverter など)の場合、デフォルト値を置き換えます。タイプ HttpMessageConverters の便利な Bean が提供され、デフォルトの MVC 構成を使用する場合は常に利用可能です。デフォルトおよびユーザー拡張のメッセージコンバーターにアクセスするための便利なメソッドがいくつかあります(例:カスタム RestTemplate に手動で挿入したい場合に便利です)。

通常の MVC の使用と同様に、提供する WebMvcConfigurer Bean は、configureMessageConverters メソッドをオーバーライドすることでコンバーターに貢献することもできます。ただし、通常の MVC とは異なり、必要な追加のコンバーターのみを提供できます(Spring Boot は同じメカニズムを使用してデフォルトを提供するため)。最後に、独自の @EnableWebMvc 構成を提供して Spring Boot のデフォルト MVC 構成をオプトアウトした場合、WebMvcConfigurationSupport から getMessageConverters を使用して完全に制御し、すべてを手動で行うことができます。

詳細については、WebMvcAutoConfiguration (GitHub) ソースコードを参照してください。

4.5. マルチパートファイルのアップロードの処理

Spring Boot は、ファイルのアップロードをサポートする Servlet 3 javax.servlet.http.Part API を採用しています。デフォルトでは、Spring Boot は、1 回のリクエストでファイルあたり最大 1MB、最大 10MB のファイルデータで Spring MVC を構成します。MultipartProperties クラスで公開されているプロパティを使用して、これらの値、中間データが保存される場所(たとえば、/tmp ディレクトリ)、およびデータがディスクにフラッシュされるしきい値をオーバーライドできます。例:ファイルを無制限に指定する場合は、spring.servlet.multipart.max-file-size プロパティを -1 に設定します。

マルチパートサポートは、Spring MVC コントローラーハンドラーメソッドで、タイプ MultipartFile の @RequestParam アノテーション付きパラメーターとしてマルチパートエンコードされたファイルデータを受信する場合に役立ちます。

詳細については、MultipartAutoConfiguration (GitHub) ソースを参照してください。

Apache Commons File Upload のような追加の依存関係を導入するのではなく、コンテナーの組み込みのマルチパートアップロードサポートを使用することをお勧めします。

4.6. Spring MVC DispatcherServlet のスイッチを切る

デフォルトでは、すべてのコンテンツはアプリケーションのルート(/)から提供されます。別のパスにマップする場合は、次のように構成できます。

spring.mvc.servlet.path=/acme

追加のサーブレットがある場合、タイプごとに Servlet または ServletRegistrationBean タイプの @Bean を宣言でき、Spring Boot はそれらをコンテナーに透過的に登録します。サーブレットはその方法で登録されるため、DispatcherServlet を呼び出さずに DispatcherServlet のサブコンテキストにマッピングできます。

DispatcherServlet を自分で構成することは珍しいことですが、本当に必要な場合は、DispatcherServletPath タイプの @Bean も提供して、カスタム DispatcherServlet のパスを提供する必要があります。

4.7. デフォルトの MVC 設定をオフにする

MVC 設定を完全に制御する最も簡単な方法は、独自の @Configuration に @EnableWebMvc アノテーションを提供することです。これを行うと、すべての MVC 設定が手元に残ります。

4.8. ViewResolvers をカスタマイズする

ViewResolver は Spring MVC のコアコンポーネントであり、@Controller のビュー名を実際の View 実装に変換します。ViewResolvers は、REST スタイルのサービスではなく、主に UI アプリケーションで使用されることに注意してください(View は @ResponseBody のレンダリングには使用されません)。ViewResolver の実装には多くの選択肢がありますが、Spring 自体は、どの実装を使用すべきかについて意見がありません。一方、Spring Boot は、クラスパスおよびアプリケーションコンテキストで検出した内容に応じて、1 つまたは 2 つをインストールします。DispatcherServlet は、アプリケーションコンテキストで見つかったすべてのリゾルバーを使用し、結果が得られるまで各リゾルバーを順番に試行します。独自のものを追加する場合、順序とリゾルバーが追加される位置に注意する必要があります。

WebMvcAutoConfiguration は、次の ViewResolvers をコンテキストに追加します。

  • 「defaultViewResolver」という名前の InternalResourceViewResolver。これは、DefaultServlet を使用してレンダリングできる物理リソース(静的リソースと JSP ページを使用する場合はそれらを含む)を見つけます。ビュー名にプレフィックスとサフィックスを適用し、サーブレットコンテキストでそのパスを持つ物理リソースを探します(デフォルトは両方とも空ですが、spring.mvc.view.prefix および spring.mvc.view.suffix を介して外部構成からアクセスできます)。同じタイプの Bean を提供することにより、オーバーライドできます。

  • 「beanNameViewResolver」という名前の BeanNameViewResolver。これは、ビューリゾルバーチェーンの有用なメンバーであり、解決される View と同じ名前の Bean をピックアップします。オーバーライドまたは置換する必要はありません。

  • 「viewResolver」という名前の ContentNegotiatingViewResolver は、実際にタイプ View の Bean が存在する 場合にのみ追加されます。これは「マスター」リゾルバーであり、他のすべてに委譲し、クライアントから送信された「Accept」HTTP ヘッダーに一致するものを見つけようとします。ContentNegotiatingViewResolver に関する有用なブログ (英語) があり、詳細を学ぶために勉強することができます。また、ソースコードを参照して詳細を調べることもできます。「viewResolver」という名前の Bean を定義することにより、自動構成された ContentNegotiatingViewResolver をオフに切り替えることができます。

  • Thymeleaf を使用する場合、「thymeleafViewResolver」という名前の ThymeleafViewResolver もあります。ビュー名をプレフィックスとサフィックスで囲むことにより、リソースを探します。プレフィックスは spring.thymeleaf.prefix で、サフィックスは spring.thymeleaf.suffix です。プレフィックスとサフィックスの値は、デフォルトでそれぞれ「classpath:/templates/」と「.html」になります。同じ名前の Bean を提供することにより、ThymeleafViewResolver をオーバーライドできます。

  • FreeMarker を使用する場合、「freeMarkerViewResolver」という名前の FreeMarkerViewResolver もあります。ビュー名を接頭辞と接尾辞で囲むことにより、ローダーパス(spring.freemarker.templateLoaderPath に外部化され、デフォルト値が「classpath:/templates/」である)でリソースを探します。プレフィックスは spring.freemarker.prefix に外部化され、サフィックスは spring.freemarker.suffix に外部化されます。プレフィックスとサフィックスのデフォルト値は、それぞれ空と「.ftlh」です。同じ名前の Bean を提供することにより、FreeMarkerViewResolver をオーバーライドできます。

  • Groovy テンプレートを使用する場合(実際には、groovy-templates がクラスパスにある場合)、「groovyMarkupViewResolver」という名前の GroovyMarkupViewResolver もあります。ビュー名を接頭辞と接尾辞(spring.groovy.template.prefix および spring.groovy.template.suffix に外部化)で囲むことにより、ローダーパス内のリソースを探します。プレフィックスとサフィックスのデフォルト値はそれぞれ「classpath:/templates/」と「.tpl」です。同じ名前の Bean を提供することにより、GroovyMarkupViewResolver をオーバーライドできます。

  • Mustache を使用する場合、「mustacheViewResolver」という名前の MustacheViewResolver もあります。ビュー名をプレフィックスとサフィックスで囲むことにより、リソースを探します。プレフィックスは spring.mustache.prefix で、サフィックスは spring.mustache.suffix です。接頭辞と接尾辞の値は、デフォルトでそれぞれ「classpath:/templates/」と「.mustache」になります。同じ名前の Bean を提供することにより、MustacheViewResolver をオーバーライドできます。

詳細については、次のセクションを参照してください。

5. Spring Security を使用したテスト

Spring Security は、特定のユーザーとしてテストを実行するためのサポートを提供します。例:以下のスニペットのテストは、ADMIN ロールを持つ認証済みユーザーで実行されます。

@Test
@WithMockUser(roles="ADMIN")
public void requestProtectedUrlWithUser() throws Exception {
    mvc
        .perform(get("/"))
        ...
}

Spring Security は Spring MVC Test との包括的な統合を提供し、これは @WebMvcTest スライスと MockMvc を使用してコントローラーをテストするときにも使用できます。

Spring Security のテストサポートの詳細については、Spring Security のリファレンスドキュメントを参照してください。

6. Jersey

6.1. Spring Security を使用した Jersey エンドポイントの保護

Spring Security は、Spring MVC ベースの Web アプリケーションを保護するために使用できるのとほぼ同じ方法で、Jersey ベースの Web アプリケーションを保護するために使用できます。ただし、Jersey で Spring Security のメソッドレベルセキュリティを使用する場合は、sendError(int) ではなく setStatus(int) を使用するように Jersey を構成する必要があります。これにより、Spring Security がクライアントに認証または認可の失敗を報告する機会を得る前に、Jersey がレスポンスをコミットすることを防ぎます。

次の例に示すように、アプリケーションの ResourceConfig Bean で jersey.config.server.response.setStatusOverSendError プロパティを true に設定する必要があります。

@Component
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        register(Endpoint.class);
        setProperties(Collections.singletonMap("jersey.config.server.response.setStatusOverSendError", true));
    }

}

6.2. 別の Web フレームワークと一緒に Jersey を使用する

Spring MVC などの別の Web フレームワークとともに Jersey を使用するには、他のフレームワークが処理できないリクエストを処理できるように構成する必要があります。最初に、filter の値で spring.jersey.type アプリケーションプロパティを設定することにより、サーブレットではなくフィルターを使用するように Jersey を設定します。次に、次の例に示すように、結果として 404 になるリクエストを転送するように ResourceConfig を構成します。

@Component
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        register(Endpoint.class);
        property(ServletProperties.FILTER_FORWARD_ON_404, true);
    }

}

7. HTTP クライアント

Spring Boot は、HTTP クライアントで動作する多くのスターターを提供します。このセクションでは、それらの使用に関する質問に回答します。

7.1. プロキシを使用するための RestTemplate の構成

spring-boot-features.html に従って、RestTemplateCustomizer と RestTemplateBuilder を使用して、カスタマイズされた RestTemplate を作成できます。これは、プロキシを使用するように構成された RestTemplate を作成するための推奨アプローチです。

プロキシ構成の正確な詳細は、使用されている基礎となるクライアントリクエストファクトリによって異なります。次の例では、192.168.0.5 を除くすべてのホストにプロキシを使用する HttpClient で HttpComponentsClientRequestFactory を構成します。

static class ProxyCustomizer implements RestTemplateCustomizer {

    @Override
    public void customize(RestTemplate restTemplate) {
        HttpHost proxy = new HttpHost("proxy.example.com");
        HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {

            @Override
            public HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context)
                    throws HttpException {
                if (target.getHostName().equals("192.168.0.5")) {
                    return null;
                }
                return super.determineProxy(target, request, context);
            }

        }).build();
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
    }

}

7.2. Reactor Netty ベースの WebClient が使用する TcpClient を構成する

Reactor Netty がクラスパスにある場合、Reactor Netty ベースの WebClient が自動構成されます。クライアントのネットワーク接続の処理をカスタマイズするには、ClientHttpConnector Bean を提供します。次の例では、60 秒の接続タイムアウトを構成し、ReadTimeoutHandler を追加します。

@Bean
ClientHttpConnector clientHttpConnector(ReactorResourceFactory resourceFactory) {
    TcpClient tcpClient = TcpClient.create(resourceFactory.getConnectionProvider())
            .runOn(resourceFactory.getLoopResources()).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60000)
            .doOnConnected((connection) -> connection.addHandlerLast(new ReadTimeoutHandler(60)));
    return new ReactorClientHttpConnector(HttpClient.from(tcpClient));
}
接続プロバイダーおよびイベントループリソースに ReactorResourceFactory を使用していることに注意してください。これにより、リクエストを受信するサーバーとリクエストを行うクライアントのリソースを効率的に共有できます。

8. ロギング

Spring Boot には、Spring Framework の spring-jcl モジュールによって通常提供される Commons Logging API を除き、必須のロギング依存関係はありません。Logback (英語) を使用するには、それと spring-jcl をクラスパスに含める必要があります。それを行う最も簡単な方法は、すべて spring-boot-starter-logging に依存するスターターを使用することです。Web アプリケーションの場合、spring-boot-starter-web のみが必要です。これは、ロギングスターターに依存するためです。Maven を使用する場合、次の依存関係によりロギングが追加されます。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot には、クラスパスのコンテンツに基づいてロギングを構成しようとする LoggingSystem 抽象化があります。Logback が利用可能な場合、それが最初の選択肢です。

ロギングに対して行う必要がある唯一の変更がさまざまなロガーのレベルの設定である場合、次の例に示すように、「logging.level」プレフィックスを使用して application.properties で設定できます。

logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

「logging.file.name」を使用して、(コンソールに加えて)ログを書き込むファイルの場所を設定することもできます。

ロギングシステムのよりきめ細かい設定を構成するには、対象の LoggingSystem でサポートされているネイティブ構成形式を使用する必要があります。デフォルトでは、Spring Boot はシステムのデフォルトの場所(Logback の場合は classpath:logback.xml など)からネイティブ構成を選択しますが、logging.config プロパティを使用して構成ファイルの場所を設定できます。

8.1. ロギング用に Logback を構成する

application.properties で達成できるもの以外に logback にカスタマイズを適用する必要がある場合は、標準の logback 構成ファイルを追加する必要があります。logback が検索できるように、logback.xml ファイルをクラスパスのルートに追加できます。Spring Boot Logback 拡張を使用する場合は、logback-spring.xml も使用できます。

Spring Boot は、独自の構成から included である多数の logback 構成を提供します。これらのインクルードは、特定の一般的な Spring Boot 規則を再適用できるように設計されています。

以下のファイルが org/springframework/boot/logging/logback/ で提供されています。

  • defaults.xml - 変換ルール、パターンプロパティ、および一般的なロガー構成を提供します。

  • console-appender.xml - CONSOLE_LOG_PATTERN を使用して ConsoleAppender を追加します。

  • file-appender.xml - 適切な設定で FILE_LOG_PATTERN および ROLLING_FILE_NAME_PATTERN を使用して RollingFileAppender を追加します。

さらに、以前のバージョンの Spring Boot との互換性のために、レガシー base.xml ファイルが提供されています。

典型的なカスタム logback.xml ファイルは次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
    <logger name="org.springframework.web" level="DEBUG"/>
</configuration>

logback 構成ファイルは、LoggingSystem が作成するシステムプロパティを利用することもできます。

  • ${PID}: 現在のプロセス ID。

  • ${LOG_FILE}logging.file.name がブートの外部構成で設定されたかどうか。

  • ${LOG_PATH}logging.file.path (ログファイルが存在するディレクトリを表す)がブートの外部設定で設定されたかどうか。

  • ${LOG_EXCEPTION_CONVERSION_WORD}logging.exception-conversion-word がブートの外部構成で設定されたかどうか。

  • ${ROLLING_FILE_NAME_PATTERN}logging.pattern.rolling-file-name がブートの外部構成で設定されたかどうか。

また、Spring Boot は、カスタム Logback コンバーターを使用して、コンソール上に(ログファイルではなく)素敵な ANSI カラーターミナル出力を提供します。例については、defaults.xml 構成の CONSOLE_LOG_PATTERN を参照してください。

Groovy がクラスパス上にある場合、logback.groovy で Logback も構成できるはずです。存在する場合、この設定が優先されます。

Spring 拡張は、Groovy 構成ではサポートされていません。logback-spring.groovy ファイルは検出されません。

8.1.1. ファイルのみの出力用に Logback を構成する

コンソールロギングを無効にし、出力のみをファイルに書き込む場合は、次の例に示すように、console-appender.xml ではなく file-appender.xml をインポートするカスタム logback-spring.xml が必要です。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
    <root level="INFO">
        <appender-ref ref="FILE" />
    </root>
</configuration>

次の例に示すように、logging.file.name を application.properties に追加する必要もあります。

logging.file.name=myapplication.log

8.2. ロギング用に Log4j を構成する

Spring Boot は、クラスパス上にある場合、ロギング構成の Log4j 2 (Apache) をサポートします。依存関係のアセンブルにスターターを使用する場合は、Logback を除外してから、代わりに log4j 2 を含める必要があります。スターターを使用しない場合は、Log4j 2 に加えて(少なくとも) spring-jcl を提供する必要があります。

最も単純なパスは、除外を使用してジグリングを必要とする場合でも、おそらくスターターを経由することです。次の例は、Maven でスターターをセットアップする方法を示しています。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

また、次の例は、Gradle でスターターをセットアップする 1 つの方法を示しています。

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-log4j2'
}

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}
Log4j スターターは、共通のロギング要件(Tomcat で java.util.logging を使用するが Log4j 2 を使用して出力を構成するなど)の依存関係を収集します。
java.util.logging を使用して実行されるデバッグロギングが Log4j 2 にルーティングされるようにするには、java.util.logging.manager システムプロパティを org.apache.logging.log4j.jul.LogManager に設定して、JDK ロギングアダプター (Apache) を構成します。

8.2.1. YAML または JSON を使用して Log4j 2 を構成する

デフォルトの XML 構成形式に加えて、Log4j 2 は YAML および JSON 構成ファイルもサポートしています。別の構成ファイル形式を使用するように Log4j 2 を構成するには、次の例に示すように、適切な依存関係をクラスパスに追加し、選択したファイル形式に合わせて構成ファイルに名前を付けます。

フォーマット 依存関係 ファイル名

YAML

com.fasterxml.jackson.core:jackson-databind + com.fasterxml.jackson.dataformat:jackson-dataformat-yaml

log4j2.yaml + log4j2.yml

JSON

com.fasterxml.jackson.core:jackson-databind

log4j2.json + log4j2.jsn

9. データアクセス

Spring Boot には、データソースを操作するためのスタータが多数含まれています。このセクションでは、その方法に関する質問に回答します。

9.1. カスタム DataSource を構成する

独自の DataSource を構成するには、構成でそのタイプの @Bean を定義します。Spring Boot は、データベースの初期化を含め、DataSource が必要な場所で再利用します。一部の設定を外部化する必要がある場合は、DataSource を環境にバインドできます(「spring-boot-features.html」を参照)。

次の例は、Bean でデータソースを定義する方法を示しています。

@Bean
@ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() {
    return new FancyDataSource();
}

次の例は、プロパティを設定してデータソースを定義する方法を示しています。

app.datasource.url=jdbc:h2:mem:mydb
app.datasource.username=sa
app.datasource.pool-size=30

FancyDataSource に URL、ユーザー名、およびプールサイズの通常の JavaBean プロパティがあると仮定すると、これらの設定は、DataSource が他のコンポーネントで使用可能になる前に自動的にバインドされます。定期的なデータベースの初期化も行われます(したがって、spring.datasource.* の関連サブセットをカスタム構成で引き続き使用できます)。

Spring Boot は、DataSourceBuilder と呼ばれるユーティリティビルダークラスも提供します。これは、標準データソースの 1 つを作成するために使用できます(クラスパス上にある場合)。ビルダーは、クラスパスで利用可能なものに基づいて、使用するものを検出できます。また、JDBC URL に基づいてドライバーを自動検出します。

次の例は、DataSourceBuilder を使用してデータソースを作成する方法を示しています。

@Bean
@ConfigurationProperties("app.datasource")
public DataSource dataSource() {
    return DataSourceBuilder.create().build();
}

その DataSource でアプリを実行するために必要なのは、接続情報だけです。プール固有の設定も提供できます。詳細については、実行時に使用される実装を確認してください。

次の例は、プロパティを設定して JDBC データソースを定義する方法を示しています。

app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30

しかし、落とし穴があります。接続プールの実際の種類が公開されていないため、カスタム DataSource のメタデータにキーが生成されず、( DataSource インターフェースはプロパティを公開しないため) IDE で補完機能を使用できません。また、クラスパスに Hikari がある場合、Hikari には url プロパティがない (ただし、jdbcUrl プロパティはある) ため、この基本セットアップは機能しません。その場合は、設定を次のように書き直す必要があります。

app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30

接続プールが DataSource ではなく専用の実装を使用して返すように強制することで、これを修正できます。実行時に実装を変更することはできませんが、オプションのリストは明示的になります。

次の例は、DataSourceBuilder で HikariDataSource を作成する方法を示しています。

@Bean
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource() {
    return DataSourceBuilder.create().type(HikariDataSource.class).build();
}

DataSourceProperties の機能を活用することで、つまり URL が提供されていない場合に適切なユーザー名とパスワードをデフォルトの組み込みデータベースに提供することで、さらに先に進むこともできます。DataSourceProperties オブジェクトの状態から DataSourceBuilder を簡単に初期化できるため、Spring Boot が自動的に作成する DataSource を挿入することもできます。ただし、その場合、構成は 2 つのネームスペースに分割されます: urlusernamepasswordtype、および spring.datasource 上の driver と残りはカスタムネームスペース(app.datasource)にあります。これを回避するには、次の例に示すように、カスタム名前空間でカスタム DataSourceProperties を再定義できます。

@Bean
@Primary
@ConfigurationProperties("app.datasource")
public DataSourceProperties dataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("app.datasource.configuration")
public HikariDataSource dataSource(DataSourceProperties properties) {
    return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}

この設定により、デフォルトで Spring Boot が行うことと同期されますが、専用の接続プールが(コードで)選択され、その設定が app.datasource.configuration サブ名前空間で公開される点が異なります。DataSourceProperties が url/jdbcUrl 変換を処理するため、次のように構成できます。

app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.configuration.maximum-pool-size=30
Spring Boot は、Hikari 固有の設定を spring.datasource.hikari に公開します。この例では複数のデータソース実装をサポートしていないため、この例ではより一般的な configuration サブ名前空間を使用します。
カスタム構成では Hikari を選択するため、app.datasource.type は効果がありません。実際には、ビルダーはそこに設定する可能性のある値で初期化され、.type() の呼び出しによってオーバーライドされます。

詳細については、「Spring Boot 機能」セクションの「spring-boot-features.html」および DataSourceAutoConfiguration (GitHub) クラスを参照してください。

9.2. 2 つの DataSources を構成する

複数のデータソースを構成する必要がある場合は、前のセクションで説明したものと同じトリックを適用できます。ただし、DataSource インスタンスの 1 つを @Primary としてマークする必要があります。今後のさまざまな自動構成では、タイプごとに 1 つを取得できると予想されるためです。

独自の DataSource を作成すると、自動構成はバックオフします。次の例では、自動構成がプライマリデータソースで提供するものとまったく同じ機能セットを提供します。

@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
public DataSourceProperties firstDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
public HikariDataSource firstDataSource() {
    return firstDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}

@Bean
@ConfigurationProperties("app.datasource.second")
public BasicDataSource secondDataSource() {
    return DataSourceBuilder.create().type(BasicDataSource.class).build();
}
データベース初期化機能がコピーを使用するように、firstDataSourceProperties に @Primary のフラグを立てる必要があります(初期化を使用する場合)。

両方のデータソースは、高度なカスタマイズにも対応しています。たとえば、次のように構成できます。

app.datasource.first.url=jdbc:mysql://localhost/first
app.datasource.first.username=dbuser
app.datasource.first.password=dbpass
app.datasource.first.configuration.maximum-pool-size=30

app.datasource.second.url=jdbc:mysql://localhost/second
app.datasource.second.username=dbuser
app.datasource.second.password=dbpass
app.datasource.second.max-total=30

次の例に示すように、セカンダリ DataSource にも同じ概念を適用できます。

@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
public DataSourceProperties firstDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
public HikariDataSource firstDataSource() {
    return firstDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}

@Bean
@ConfigurationProperties("app.datasource.second")
public DataSourceProperties secondDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("app.datasource.second.configuration")
public BasicDataSource secondDataSource() {
    return secondDataSourceProperties().initializeDataSourceBuilder().type(BasicDataSource.class).build();
}

前の例では、Spring Boot が自動構成で使用するのと同じロジックを使用して、カスタム名前空間に 2 つのデータソースを構成します。各 configuration サブ名前空間は、選択した実装に基づいて高度な設定を提供することに注意してください。

9.3. Spring Data リポジトリを使用する

Spring Data は、さまざまなフレーバーの @Repository インターフェースの実装を作成できます。@Repositories が @EnableAutoConfiguration クラスの同じパッケージ(またはサブパッケージ)に含まれている限り、Spring Boot はそれらすべてを処理します。

多くのアプリケーションで必要なのは、クラスパスに正しい Spring Data 依存関係を置くことだけです。JPA には spring-boot-starter-data-jpa、Mongodb には spring-boot-starter-data-mongodb などがあります。開始するには、@Entity オブジェクトを処理するリポジトリインターフェースをいくつか作成します。

Spring Boot は、検出した @EnableAutoConfiguration に基づいて、@Repository 定義の場所を推測しようとします。さらに制御するには、@EnableJpaRepositories アノテーション(Spring Data JPA から)を使用します。

Spring Data の詳細については、Spring Data プロジェクトページを参照してください。

9.4. Spring 構成から @Entity 定義を分離する

Spring Boot は、検出した @EnableAutoConfiguration に基づいて、@Entity 定義の場所を推測しようとします。さらに制御するには、次の例に示すように、@EntityScan アノテーションを使用できます。

@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
public class Application {

    //...

}

9.5. JPA プロパティの構成

Spring Data JPA は、ベンダーに依存しないいくつかの構成オプション(SQL ロギングのオプションなど)をすでに提供しており、Spring Boot はそれらのオプションと Hibernate のいくつかを外部構成プロパティとして公開しています。それらの一部はコンテキストに従って自動的に検出されるため、設定する必要はありません。

spring.jpa.hibernate.ddl-auto は、ランタイム条件に応じて異なるデフォルト値を持っているため、特別なケースです。組み込みデータベースが使用され、スキーママネージャー(Liquibase や Flyway など)が DataSource を処理していない場合、デフォルトは create-drop になります。他のすべての場合、デフォルトは none です。

使用するダイアレクトは JPA プロバイダーによって検出されます。ダイアレクトを自分で設定する場合は、spring.jpa.database-platform プロパティを設定します。

設定する最も一般的なオプションを次の例に示します。

spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy
spring.jpa.show-sql=true

また、spring.jpa.properties.* のすべてのプロパティは、ローカル EntityManagerFactory が作成されるときに、通常の JPA プロパティとして(プレフィックスが削除された状態で)渡されます。

spring.jpa.properties.* で定義された名前が、JPA プロバイダーが期待する名前と正確に一致することを確認する必要があります。Spring Boot は、これらのエントリに対して緩いバインディングを試みません。

例:Hibernate のバッチサイズを設定する場合は、spring.jpa.properties.hibernate.jdbc.batch_size を使用する必要があります。batchSize や batch-size などの他のフォームを使用する場合、Hibernate は設定を適用しません。

Hibernate プロパティに高度なカスタマイズを適用する必要がある場合は、EntityManagerFactory を作成する前に呼び出される HibernatePropertiesCustomizer Bean を登録することを検討してください。これは、自動構成によって適用されるものよりも優先されます。

9.6. Hibernate 命名戦略の構成

Hibernate は、2 つの異なる命名戦略 (英語) を使用して、オブジェクトモデルから対応するデータベース名に名前をマッピングします。spring.jpa.hibernate.naming.physical-strategy プロパティと spring.jpa.hibernate.naming.implicit-strategy プロパティをそれぞれ設定することにより、物理的および暗黙的な戦略実装の完全修飾クラス名を構成できます。または、ImplicitNamingStrategy または PhysicalNamingStrategy Bean がアプリケーションコンテキストで使用可能な場合、Hibernate はそれらを使用するように自動的に構成されます。

デフォルトでは、Spring Boot は SpringPhysicalNamingStrategy を使用して物理命名戦略を構成します。この実装は、Hibernate 4: と同じテーブル構造を提供します。すべてのドットがアンダースコアに置き換えられ、キャメルケーシングもアンダースコアに置き換えられます。デフォルトでは、すべてのテーブル名は小文字で生成されますが、スキーマで必要な場合は、そのフラグをオーバーライドできます。

例: TelephoneNumber エンティティは telephone_number テーブルにマッピングされます。

代わりに Hibernate 5 のデフォルトを使用する場合は、次のプロパティを設定します。

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

または、次の Bean を構成できます。

@Bean
public PhysicalNamingStrategy physicalNamingStrategy() {
    return new PhysicalNamingStrategyStandardImpl();
}

詳細については、HibernateJpaAutoConfiguration (GitHub) および JpaBaseConfiguration (GitHub) を参照してください。

9.7. Hibernate 2 次キャッシュを構成する

Hibernate 2 次キャッシュ (英語) は、さまざまなキャッシュプロバイダーに対して構成できます。キャッシュプロバイダーを再度検索するように Hibernate を構成するのではなく、可能な場合はコンテキストで利用可能なものを提供することをお勧めします。

JCache を使用している場合、これは非常に簡単です。最初に、org.hibernate:hibernate-jcache がクラスパスで利用可能であることを確認してください。次に、次の例に示すように、HibernatePropertiesCustomizer Bean を追加します。

@Configuration(proxyBeanMethods = false)
public class HibernateSecondLevelCacheExample {

    @Bean
    public HibernatePropertiesCustomizer hibernateSecondLevelCacheCustomizer(JCacheCacheManager cacheManager) {
        return (properties) -> properties.put(ConfigSettings.CACHE_MANAGER, cacheManager.getCacheManager());
    }

}

このカスタマイザーは、アプリケーションが使用するものと同じ CacheManager を使用するように Hibernate を構成します。別の CacheManager インスタンスを使用することもできます。詳細については、Hibernate ユーザーガイドを参照してください (英語)

9.8. Hibernate コンポーネントでの依存性注入の使用

デフォルトでは、Spring Boot は BeanFactory を使用する BeanContainer 実装を登録して、コンバーターとエンティティリスナーが通常の依存性注入を使用できるようにします。

hibernate.resource.beans.container プロパティを削除または変更する HibernatePropertiesCustomizer を登録することにより、この動作を無効化または調整できます。

9.9. カスタム EntityManagerFactory を使用する

EntityManagerFactory の構成を完全に制御するには、「entityManagerFactory」という名前の @Bean を追加する必要があります。Spring Boot 自動構成は、そのタイプの Bean が存在する場合、エンティティマネージャーをオフにします。

9.10. EntityManagers を 2 つ使用する

デフォルトの EntityManagerFactory が正常に機能する場合でも、新しいものを定義する必要があります。そうでない場合、そのタイプの 2 番目の Bean が存在すると、デフォルトがオフになります。簡単にするために、Spring Boot が提供する便利な EntityManagerBuilder を使用できます。または、次の例に示すように、Spring ORM から直接 LocalContainerEntityManagerFactoryBean のみを実行できます。

// add two data sources configured as above

@Bean
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
        EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(customerDataSource())
            .packages(Customer.class)
            .persistenceUnit("customers")
            .build();
}

@Bean
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
        EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(orderDataSource())
            .packages(Order.class)
            .persistenceUnit("orders")
            .build();
}
LocalContainerEntityManagerFactoryBean 用の Bean を自分で作成すると、自動構成された LocalContainerEntityManagerFactoryBean の作成中に適用されたカスタマイズは失われます。例:Hibernate の場合、spring.jpa.hibernate プレフィックスのプロパティは LocalContainerEntityManagerFactoryBean に自動的に適用されません。命名戦略や DDL モードなどを設定するためにこれらのプロパティに依存していた場合、LocalContainerEntityManagerFactoryBean Bean を作成するときに明示的に設定する必要があります。一方、spring.jpa.properties を介して指定された自動構成 EntityManagerFactoryBuilder に適用されるプロパティは、自動構成 EntityManagerFactoryBuilder を使用して LocalContainerEntityManagerFactoryBean Bean を構築する場合に自動的に適用されます。

上記の構成は、ほとんど単独で機能します。図を完成させるには、2 つの EntityManagers の TransactionManagers も構成する必要があります。それらのいずれかを @Primary としてマークすると、Spring Boot のデフォルトの JpaTransactionManager によってピックアップされる可能性があります。もう 1 つは、新しいインスタンスに明示的に挿入する必要があります。または、両方にまたがる JTA トランザクションマネージャーを使用できる場合があります。

Spring Data を使用する場合、次の例に示すように、それに応じて @EnableJpaRepositories を構成する必要があります。

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Customer.class,
        entityManagerFactoryRef = "customerEntityManagerFactory")
public class CustomerConfiguration {
    ...
}

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Order.class,
        entityManagerFactoryRef = "orderEntityManagerFactory")
public class OrderConfiguration {
    ...
}

9.11. 従来の persistence.xml ファイルを使用する

Spring Boot は、デフォルトでは META-INF/persistence.xml を検索または使用しません。従来の persistence.xml を使用する場合は、タイプ LocalEntityManagerFactoryBean の独自の @Bean (「entityManagerFactory」の ID を使用)を定義し、そこに永続性ユニット名を設定する必要があります。

デフォルト設定については、JpaBaseConfiguration (GitHub) を参照してください。

9.12. Spring Data JPA および Mongo リポジトリを使用する

Spring Data JPA と Spring Data Mongo はどちらも Repository 実装を自動的に作成できます。両方がクラスパスに存在する場合は、Spring Boot に作成するリポジトリを指示するために、追加の構成が必要になる場合があります。最も明示的な方法は、標準の Spring Data @EnableJpaRepositories および @EnableMongoRepositories アノテーションを使用して、Repository インターフェースの場所を提供することです。

外部構成で自動構成リポジトリのオンとオフを切り替えるために使用できるフラグ(spring.data.*.repositories.enabled および spring.data.*.repositories.type)もあります。これは、たとえば、Mongo リポジトリをオフにし、自動構成された MongoTemplate を使用したい場合に役立ちます。

他の自動構成された Spring Data リポジトリタイプ(Elasticsearch、Solr など)にも同じ障害と同じ機能が存在します。使用するには、アノテーションの名前とフラグを適宜変更します。

9.13. Spring Data の Web サポートのカスタマイズ

Spring Data は、Web アプリケーションで Spring Data リポジトリの使用を簡素化する Web サポートを提供します。Spring Boot は、構成をカスタマイズするために spring.data.web 名前空間にプロパティを提供します。Spring Data REST を使用している場合、代わりに spring.data.rest 名前空間のプロパティを使用する必要があることに注意してください。

9.14. Spring Data リポジトリを REST エンドポイントとして公開する

Spring MVC がアプリケーションで有効になっている場合、Spring Data REST は Repository 実装を REST エンドポイントとして公開できます。

Spring Boot は、RepositoryRestConfiguration (英語) をカスタマイズする一連の有用なプロパティ(spring.data.rest 名前空間から)を公開します。追加のカスタマイズを提供する必要がある場合は、RepositoryRestConfigurer (英語) Bean を使用する必要があります。

カスタム RepositoryRestConfigurer で順序を指定しない場合、Spring Boot が内部的に使用した後に実行されます。順序を指定する必要がある場合は、0 より大きいことを確認してください。

9.15. JPA によって使用されるコンポーネントを構成する

JPA が使用するコンポーネントを構成する場合は、JPA の前にコンポーネントが初期化されていることを確認する必要があります。コンポーネントが自動構成されると、Spring Boot がこれを処理します。例:Flyway が自動構成されている場合、Hibernate は Flyway に依存するように構成されているため、Flyway は Hibernate がデータベースを使用しようとする前にデータベースを初期化できます。

コンポーネントを自分で構成する場合は、EntityManagerFactoryDependsOnPostProcessor サブクラスを使用して、必要な依存関係をセットアップする便利な方法として使用できます。例:インデックスマネージャーとして Elasticsearch で Hibernate Search を使用する場合、次の例に示すように、EntityManagerFactory Bean は elasticsearchClient Bean に依存するように構成する必要があります。

/**
 * {@link EntityManagerFactoryDependsOnPostProcessor} that ensures that
 * {@link EntityManagerFactory} beans depend on the {@code elasticsearchClient} bean.
 */
@Component
static class ElasticsearchEntityManagerFactoryDependsOnPostProcessor
        extends EntityManagerFactoryDependsOnPostProcessor {

    ElasticsearchEntityManagerFactoryDependsOnPostProcessor() {
        super("elasticsearchClient");
    }

}

9.16. 2 つの DataSources で jOOQ を構成する

jOOQ を複数のデータソースで使用する必要がある場合は、それぞれに対して独自の DSLContext を作成する必要があります。詳細については、JooqAutoConfiguration (GitHub) を参照してください。

特に、JooqExceptionTranslator および SpringTransactionProvider を再利用して、単一の DataSource で自動構成が行うことと同様の機能を提供できます。

10. データベースの初期化

SQL データベースは、スタックの種類に応じてさまざまな方法で初期化できます。もちろん、データベースが別のプロセスであれば、手動で行うこともできます。スキーマ生成には単一のメカニズムを使用することをお勧めします。

10.1. JPA を使用してデータベースを初期化する

JPA には DDL 生成のための機能があり、これらはデータベースに対して起動時に実行されるように設定できます。これは、2 つの外部プロパティによって制御されます。

  • spring.jpa.generate-ddl (ブール型)は、機能のオンとオフを切り替え、ベンダーに依存しません。

  • spring.jpa.hibernate.ddl-auto (enum)は、よりきめ細かい方法で動作を制御する Hibernate 機能です。この機能については、このガイドの後半で詳しく説明します。

10.2. Hibernate を使用したデータベースの初期化

spring.jpa.hibernate.ddl-auto を明示的に設定でき、標準の Hibernate プロパティ値は nonevalidateupdatecreate および create-drop です。Spring Boot は、データベースが埋め込まれていると考えるかどうかに基づいて、デフォルト値を選択します。スキーママネージャーが検出されなかった場合はデフォルトで create-drop になり、それ以外の場合は none になります。Connection タイプを調べると、組み込みデータベースが検出されます。hsqldbh2 および derby は埋め込まれていますが、その他は埋め込まれていません。メモリ内から「実際の」データベースに切り替えるときは、新しいプラットフォーム内のテーブルとデータの存在について仮定しないように注意してください。ddl-auto を明示的に設定するか、他のメカニズムのいずれかを使用してデータベースを初期化する必要があります。

org.hibernate.SQL ロガーを有効にすることにより、スキーマ作成を出力できます。これは、デバッグモードを有効にすると自動的に行われます。

さらに、Hibernate が最初からスキーマを作成する場合(つまり、ddl-auto プロパティが create または create-drop に設定される場合)、クラスパスのルートにある import.sql という名前のファイルが起動時に実行されます。これは、デモや、慎重にテストする場合に役立ちますが、おそらく本番環境のクラスパスに配置したいものではありません。これは Hibernate 機能です(Spring とは関係ありません)。

10.3. 基本的な SQL スクリプトを使用してデータベースを初期化する

Spring Boot は、DataSource のスキーマ(DDL スクリプト)を自動的に作成し、それを初期化できます(DML スクリプト)。標準のルートクラスパスの場所、それぞれ schema.sql および data.sql から SQL をロードします。さらに、Spring Boot は schema-${platform}.sql および data-${platform}.sql ファイル(存在する場合)を処理します。platform は spring.datasource.platform の値です。これにより、必要に応じてデータベース固有のスクリプトに切り替えることができます。例:データベースのベンダー名に設定することもできます(hsqldbh2oraclemysqlpostgresql など)。

基本的な SQL スクリプトのみが使用される場合、Spring Boot は埋め込まれた DataSource のスキーマを自動的に作成します。この動作は、spring.datasource.initialization-mode プロパティを使用してカスタマイズできます。たとえば、DataSource をそのタイプに関係なく常に初期化したい場合:

spring.datasource.initialization-mode=always

JPA ベースのアプリでは、Hibernate にスキーマを作成させるか、schema.sql を使用させるかを選択できますが、両方を行うことはできません。schema.sql を使用する場合は、spring.jpa.hibernate.ddl-auto を必ず無効にしてください。

spring.jpa.hibernate.ddl-auto=none

Flyway や Liquibase などの高レベルのデータベース移行ツールを使用している場合、基本的な SQL スクリプトを使用してスキーマを作成および初期化することはできません。この場合、schema.sql と data.sql が存在しても無視されます。データベース移行ツールを使用してスキーマの作成を管理したり、基本的な SQL スクリプトを使用してスキーマを初期化することはできません。

デフォルトでは、Spring Boot は Spring JDBC イニシャライザーのフェイルファースト機能を有効にします。これは、スクリプトが例外を引き起こす場合、アプリケーションの起動に失敗することを意味します。spring.datasource.continue-on-error を設定することにより、その動作を調整できます。

10.4. R2DBC を使用してデータベースを初期化する

R2DBC を使用している場合、通常の DataSource 自動構成がバックオフされるため、上記のオプションはいずれも使用できません。

Spring Data R2DBC を使用している場合、次の例に示すように、簡単な SQL スクリプトを使用して起動時にデータベースを初期化できます。

@Configuration(proxyBeanMethods = false)
static class DatabaseInitializationConfiguration {

    @Autowired
    void initializeDatabase(ConnectionFactory connectionFactory) {
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource[] scripts = new Resource[] { resourceLoader.getResource("classpath:schema.sql"),
                resourceLoader.getResource("classpath:data.sql") };
        new ResourceDatabasePopulator(scripts).execute(connectionFactory).block();
    }

}

または、Flyway または Liquibase のいずれかを構成して、移行中の DataSource を構成することができます。これらのライブラリはどちらも、移行するデータベースの urlusername および password を設定するプロパティを提供します。

このオプションを選択する場合、org.springframework:spring-jdbc は依然として必須の依存関係です。

10.5. Spring Batch データベースを初期化する

Spring Batch を使用する場合、ほとんどの一般的なデータベースプラットフォーム用の SQL 初期化スクリプトがあらかじめパッケージ化されています。Spring Boot は、データベースタイプを検出し、起動時にこれらのスクリプトを実行できます。組み込みデータベースを使用する場合、これはデフォルトで行われます。次の例に示すように、任意のデータベースタイプに対して有効にすることもできます。

spring.batch.initialize-schema=always

spring.batch.initialize-schema=never を設定して、初期化を明示的にオフにすることもできます。

10.6. 高レベルのデータベース移行ツールを使用する

Spring Boot は、Flyway (英語) Liquibase (英語) の 2 つの高レベルの移行ツールをサポートしています。

10.6.1. 起動時に Flyway データベース移行を実行する

起動時に Flyway データベースの移行を自動的に実行するには、org.flywaydb:flyway-core をクラスパスに追加します。

通常、移行は V<VERSION>__<NAME>.sql という形式のスクリプトです(<VERSION> は、「1」や「2_1」などのアンダースコアで区切られたバージョンです)。デフォルトでは、これらは classpath:db/migration と呼ばれるディレクトリにありますが、spring.flyway.locations を設定することでその場所を変更できます。これは、1 つ以上の classpath: または filesystem: ロケーションのコンマ区切りリストです。例:次の構成では、デフォルトのクラスパスの場所と /opt/migration ディレクトリの両方でスクリプトを検索します。

spring.flyway.locations=classpath:db/migration,filesystem:/opt/migration

特別な {vendor} プレースホルダーを追加して、ベンダー固有のスクリプトを使用することもできます。以下を想定します。

spring.flyway.locations=classpath:db/migration/{vendor}

db/migration を使用するのではなく、前述の構成では、データベースのタイプ(MySQL の db/migration/mysql など)に従って使用するディレクトリを設定します。サポートされているデータベースのリストは、DatabaseDriver (GitHub) で入手できます。

移行は Java で作成することもできます。Flyway は、JavaMigration を実装する Bean で自動構成されます。

FlywayProperties (GitHub) は、Flyway のほとんどの設定と、移行を無効にするか、場所の確認をオフにするために使用できる追加プロパティの小さなセットを提供します。構成をさらに制御する必要がある場合は、FlywayConfigurationCustomizer Bean の登録を検討してください。

Spring Boot は Flyway.migrate() を呼び出して、データベースの移行を実行します。さらに制御したい場合は、FlywayMigrationStrategy (GitHub) を実装する @Bean を提供してください。

Flyway は SQL および Java コールバック (英語) をサポートします。SQL ベースのコールバックを使用するには、コールバックスクリプトを classpath:db/migration ディレクトリに配置します。Java ベースのコールバックを使用するには、Callback を実装する 1 つ以上の Bean を作成します。このような Bean は Flyway に自動的に登録されます。@Order を使用するか、Ordered を実装することでオーダーできます。非推奨の FlywayCallback インターフェースを実装する Bean も検出できますが、Callback Bean と一緒に使用することはできません。

デフォルトでは、Flyway はコンテキストで(@Primary) DataSource をオートワイヤーし、それを移行に使用します。別の DataSource を使用する場合は、作成して、その @Bean を @FlywayDataSource としてマークできます。そのようにして 2 つのデータソースが必要な場合は、別のデータソースを作成して @Primary としてマークしてください。または、外部プロパティで spring.flyway.[url,user,password] を設定することにより、Flyway のネイティブ DataSource を使用できます。spring.flyway.url または spring.flyway.user のいずれかを設定するだけで、Flyway が独自の DataSource を使用できます。3 つのプロパティのいずれかが設定されていない場合、同等の spring.datasource プロパティの値が使用されます。

Flyway を使用して、特定のシナリオのデータを提供することもできます。例:テスト固有の移行を src/test/resources に配置できます。これらの移行は、テストのためにアプリケーションが開始されたときにのみ実行されます。また、特定のプロファイルがアクティブな場合にのみ特定の移行が実行されるように、プロファイル固有の構成を使用して spring.flyway.locations をカスタマイズできます。例: application-dev.properties では、次の設定を指定できます。

spring.flyway.locations=classpath:/db/migration,classpath:/dev/db/migration

その設定では、dev/db/migration の移行は、dev プロファイルがアクティブな場合にのみ実行されます。

10.6.2. 起動時に Liquibase データベースの移行を実行する

起動時に Liquibase データベースの移行を自動的に実行するには、クラスパスに org.liquibase:liquibase-core を追加します。

org.liquibase:liquibase-core をクラスパスに追加すると、アプリケーションの起動時とテストの実行前の両方で、データベースの移行がデフォルトで実行されます。この動作は、spring.liquibase.enabled プロパティを使用してカスタマイズでき、main および test 構成で異なる値を設定します。2 つの異なる方法でデータベースを初期化することはできません(アプリケーションの起動には Liquibase、テスト実行には JPA など)。

デフォルトでは、マスター変更ログは db/changelog/db.changelog-master.yaml から読み取られますが、spring.liquibase.change-log を設定して場所を変更できます。YAML に加えて、Liquibase は JSON、XML、および SQL 変更ログ形式もサポートしています。

デフォルトでは、Liquibase は(@Primary) DataSource をコンテキストでオートワイヤーし、それを移行に使用します。別の DataSource を使用する必要がある場合は、それを作成して、その @Bean を @LiquibaseDataSource としてマークできます。その場合、2 つのデータソースが必要な場合は、別のデータソースを作成して、@Primary としてマークすることを忘れないでください。または、外部プロパティで spring.liquibase.[url,user,password] を設定することにより、Liquibase のネイティブ DataSource を使用できます。Liquibase が独自の DataSource を使用するには、spring.liquibase.url または spring.liquibase.user を設定するだけで十分です。3 つのプロパティのいずれかが設定されていない場合、対応する spring.datasource プロパティの値が使用されます。

コンテキスト、デフォルトスキーマなどの利用可能な設定の詳細については、LiquibaseProperties (GitHub) を参照してください。

11. メッセージング

Spring Boot は、メッセージングを含む多くのスターターを提供します。このセクションでは、Spring Boot でメッセージングを使用することから生じる質問に回答します。

11.1. トランザクション JMS セッションを無効にする

JMS ブローカーがトランザクションセッションをサポートしていない場合、トランザクションのサポートを完全に無効にする必要があります。独自の JmsListenerContainerFactory を作成する場合、デフォルトではトランザクションを処理できないため、実行することはありません。DefaultJmsListenerContainerFactoryConfigurer を使用して Spring Boot のデフォルトを再利用する場合、次のようにトランザクションセッションを無効にできます。

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(
        ConnectionFactory connectionFactory,
        DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory listenerFactory =
            new DefaultJmsListenerContainerFactory();
    configurer.configure(listenerFactory, connectionFactory);
    listenerFactory.setTransactionManager(null);
    listenerFactory.setSessionTransacted(false);
    return listenerFactory;
}

前述の例はデフォルトのファクトリをオーバーライドします。アプリケーションが定義する他のファクトリがある場合は、それを適用する必要があります。

12. バッチアプリケーション

Spring Boot アプリケーション内から Spring Batch を使用する場合、多くの質問がしばしば発生します。このセクションでは、これらの質問に対処します。

12.1. バッチデータソースの指定

デフォルトでは、バッチアプリケーションには、ジョブの詳細を保存するために DataSource が必要です。Spring Batch は、デフォルトで単一の DataSource を想定しています。アプリケーションのメイン DataSource 以外の DataSource を使用するには、DataSource Bean を宣言し、@BatchDataSource で @Bean メソッドにアノテーションを付けます。その場合、2 つのデータソースが必要な場合は、もう 1 つのデータソースを @Primary としてマークすることを忘れないでください。制御を強化するには、BatchConfigurer を実装します。詳細については、@EnableBatchProcessing の Javadoc を参照してください。

Spring Batch の詳細については、Spring Batch プロジェクトページを参照してください。

12.2. 起動時に Spring Batch ジョブを実行する

@EnableBatchProcessing を @Configuration クラスの 1 つに追加すると、Spring Batch の自動構成が有効になります。

デフォルトでは、起動時にアプリケーションコンテキストですべての Jobs を実行します(詳細については JobLauncherApplicationRunner (GitHub) を参照)。spring.batch.job.names (ジョブ名パターンのコンマ区切りリストを使用)を指定することにより、特定のジョブに絞り込むことができます。

詳細については、BatchAutoConfiguration (GitHub) および @EnableBatchProcessing(Javadoc) を参照してください。

12.3. コマンドラインから実行する

Spring Boot は、-- で始まるコマンドライン引数をプロパティに変換して、Environment に追加します。コマンドラインプロパティへのアクセスを参照してください。これは、バッチジョブに引数を渡すために使用しないでください。コマンドラインでバッチ引数を指定するには、次の例に示すように、通常の形式(つまり -- なし)を使用します。

$ java -jar myapp.jar someParameter=someValue anotherParameter=anotherValue

コマンドラインで Environment のプロパティを指定すると、ジョブによって無視されます。次のコマンドを検討してください。

$ java -jar myapp.jar --server.port=7070 someParameter=someValue

これは、バッチジョブに 1 つの引数 someParameter=someValue のみを提供します。

12.4. ジョブリポジトリの保存

Spring Batch では、Job リポジトリ用のデータストアが必要です。Spring Boot を使用する場合、実際のデータベースを使用する必要があります。インメモリデータベースでもかまいません。ジョブリポジトリの構成を参照してください。

13. アクチュエーター

Spring Boot には Spring Boot Actuator が含まれます。このセクションでは、その使用からしばしば生じる質問に回答します。

13.1. アクチュエーターエンドポイントの HTTP ポートまたはアドレスを変更する

スタンドアロンアプリケーションでは、アクチュエーターの HTTP ポートはデフォルトでメイン HTTP ポートと同じになります。アプリケーションが別のポートでリッスンするようにするには、外部プロパティ management.server.port を設定します。管理用の内部ネットワークとユーザーアプリケーション用の外部ネットワークがある場合など、完全に異なるネットワークアドレスでリッスンするために、management.server.address をサーバーがバインドできる有効な IP アドレスに設定することもできます。

詳細については、ManagementServerProperties (GitHub) ソースコードおよび「Production-ready features」セクションの「production-ready-features.html」を参照してください。

13.2. 「ホワイトラベル」エラーページをカスタマイズする

Spring Boot は、サーバーエラーが発生した場合にブラウザークライアントに表示される「ホワイトラベル」エラーページをインストールします(JSON およびその他のメディアタイプを使用するマシンクライアントは、適切なエラーコードで適切なレスポンスを確認する必要があります)。

server.error.whitelabel.enabled=false を設定して、デフォルトのエラーページをオフにします。これにより、使用しているサーブレットコンテナーのデフォルトが復元されます。Spring Boot は引き続きエラービューの解決を試みるため、完全に無効にするのではなく、おそらく独自のエラーページを追加する必要があります。

エラーページを独自のもので上書きするかどうかは、使用するテンプレートテクノロジによって異なります。例:Thymeleaf を使用する場合、error.html テンプレートを追加できます。FreeMarker を使用する場合、error.ftlh テンプレートを追加できます。一般的に、error または /error パスを処理する @Controller の名前で解決される View が必要です。いくつかのデフォルト構成を置き換えない限り、ApplicationContext で BeanNameViewResolver を見つける必要があります。そのため、error という名前の @Bean がそれを行う簡単な方法です。その他のオプションについては、ErrorMvcAutoConfiguration (GitHub) を参照してください。

サーブレットコンテナーにハンドラーを登録する方法の詳細については、「エラー処理」のセクションも参照してください。

13.3. 機密値を無害化する

env エンドポイントと configprops エンドポイントによって返される情報はやや機密性が高いため、特定のパターンに一致するキーはデフォルトでサニタイズされます(つまり、それらの値は ****** に置き換えられます)。

使用するパターンは、それぞれ management.endpoint.env.keys-to-sanitize と management.endpoint.configprops.keys-to-sanitize を使用してカスタマイズできます。

Spring Boot は、そのようなキーに適切なデフォルトを使用します。「password」、「secret」、「key」、「token」、「vcap_services」、「sun.java.command」、「uri」、「uris」、「住所」または「住所」はサニタイズされます。さらに、credentials という単語をキーの一部として保持するキーはすべてサニタイズされます(正規表現、つまり .*credentials.* として構成されます)。

サニタイズするキーのいずれかが URI 形式(つまり <scheme>://<username>:<password>@<host>:<port>/)の場合、パスワード部分のみがサニタイズされます。

13.4. ヘルスインジケーターを Micrometer メトリックにマップする

Spring Boot ヘルスインジケーターは、システム全体のヘルスを示す Status タイプを返します。特定のアプリケーションのヘルスレベルを監視またはアラートする場合は、Micrometer を介してこれらのステータスをメトリックとしてエクスポートできます。デフォルトでは、ステータスコード「UP」、「DOWN」、「OUT_OF_SERVICE」、「UNKNOWN」が Spring Boot によって使用されます。これらをエクスポートするには、これらの状態をいくつかの数値セットに変換して、Micrometer Gauge で使用できるようにする必要があります。

次の例は、そのようなエクスポーターを作成する 1 つの方法を示しています。

@Configuration
public class HealthMetricsConfiguration {

    public HealthMetricsConfiguration(MeterRegistry registry, HealthEndpoint healthEndpoint) {
        // This example presumes common tags (such as the app) are applied elsewhere
        Gauge.builder("health", healthEndpoint, this::getStatusCode).strongReference(true).register(registry);
    }

    private int getStatusCode(HealthEndpoint health) {
        Status status = health.health().getStatus();
        if (Status.UP.equals(status)) {
            return 3;
        }
        if (Status.OUT_OF_SERVICE.equals(status)) {
            return 2;
        }
        if (Status.DOWN.equals(status)) {
            return 1;
        }
        return 0;
    }

}

14. セキュリティ

このセクションでは、Spring Boot で Spring Security を使用することから生じる質問を含む、Spring Boot を使用する際のセキュリティに関する質問について説明します。

Spring Security の詳細については、Spring Security プロジェクトページを参照してください。

14.1. Spring Boot セキュリティ構成をオフにする

アプリケーションで @Configuration を WebSecurityConfigurerAdapter で定義すると、Spring Boot のデフォルトの webapp セキュリティ設定がオフになります。

14.2. UserDetailsService の変更とユーザーアカウントの追加

タイプ AuthenticationManagerAuthenticationProvider または UserDetailsService の @Bean を提供する場合、InMemoryUserDetailsManager のデフォルト @Bean は作成されません。これは、Spring Security の完全な機能セット(さまざまな認証オプションなど)を使用できることを意味します。

ユーザーアカウントを追加する最も簡単な方法は、独自の UserDetailsService Bean を提供することです。

14.3. プロキシサーバーの背後で実行するときに HTTPS を有効にする

すべてのメインエンドポイントが HTTPS 経由でのみ使用できるようにすることは、アプリケーションにとって重要な作業です。Tomcat をサーブレットコンテナーとして使用している場合、Spring Boot は、一部の環境設定を検出すると Tomcat 自身の RemoteIpValve を自動的に追加し、HttpServletRequest に依存して、安全かどうか(処理するプロキシサーバーの下流であっても)を報告できるはずです実際の SSL 終了)。標準の動作は、名前が従来のものである特定のリクエストヘッダー(x-forwarded-for および x-forwarded-proto)の有無によって決定されるため、ほとんどのフロントエンドプロキシで動作するはずです。次の例に示すように、application.properties にいくつかのエントリを追加することにより、バルブをオンに切り替えることができます。

server.tomcat.remoteip.remote-ip-header=x-forwarded-for
server.tomcat.remoteip.protocol-header=x-forwarded-proto

(これらのプロパティのいずれかが存在すると、バルブが切り替わります。または、TomcatServletWebServerFactory Bean を追加して RemoteIpValve を追加できます)

Spring Security を構成して、すべての(または一部の)リクエストにセキュアチャネルをリクエストするには、次の HttpSecurity 構成を追加する独自の WebSecurityConfigurerAdapter を追加することを検討してください。

@Configuration(proxyBeanMethods = false)
public class SslWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Customize the application security
        http.requiresChannel().anyRequest().requiresSecure();
    }

}

15. ホットスワップ

Spring Boot はホットスワップをサポートしています。このセクションでは、その仕組みに関する質問に回答します。

15.1. 静的コンテンツをリロードする

ホットリロードにはいくつかのオプションがあります。推奨されるアプローチは spring-boot-devtools を使用することです。これは、アプリケーションの高速再起動や LiveReload のサポートなどの追加の開発時機能、および実用的な開発時設定(テンプレートキャッシングなど)を提供するためです。Devtools は、クラスパスの変更を監視することで機能します。つまり、変更を有効にするには、静的リソースの変更を「構築」する必要があります。デフォルトでは、変更を保存すると、Eclipse でこれが自動的に行われます。IntelliJ IDEA では、プロジェクトの作成コマンドが必要なビルドをトリガーします。デフォルトの再起動の除外により、静的リソースを変更してもアプリケーションの再起動はトリガーされません。ただし、ライブリロードはトリガーされます。

あるいは、IDE で実行する(特にデバッグをオンにした)ことは、開発を行うための良い方法です(すべての最新の IDE は静的リソースの再読み込みを許可し、通常 Java クラス変更のホットスワップも許可します)。

最後に、Maven および Gradle プラグインを構成して(addResources プロパティを参照)、ソースから直接静的ファイルをリロードするコマンドラインからの実行をサポートできます。より高いレベルのツールを使用してコードを記述している場合は、外部の css/js コンパイラプロセスで使用できます。

15.2. コンテナーを再起動せずにテンプレートをリロードする

Spring Boot でサポートされるほとんどのテンプレートテクノロジには、キャッシュを無効にする構成オプションが含まれています(このドキュメントで後述)。spring-boot-devtools モジュールを使用する場合、これらのプロパティは開発時に自動的に構成されます。

15.2.1. Thymeleaf テンプレート

Thymeleaf を使用する場合は、spring.thymeleaf.cache を false に設定します。他の Thymeleaf カスタマイズオプションについては、ThymeleafAutoConfiguration (GitHub) を参照してください。

15.2.2. FreeMarker テンプレート

FreeMarker を使用する場合は、spring.freemarker.cache を false に設定します。他の FreeMarker カスタマイズオプションについては、FreeMarkerAutoConfiguration (GitHub) を参照してください。

15.2.3. Groovy テンプレート

Groovy テンプレートを使用する場合、spring.groovy.template.cache を false に設定します。他の Groovy カスタマイズオプションについては、GroovyTemplateAutoConfiguration (GitHub) を参照してください。

15.3. 高速アプリケーション再起動

spring-boot-devtools モジュールには、自動アプリケーション再起動のサポートが含まれています。JRebel (英語) などのテクノロジーほど高速ではありませんが、通常は「コールドスタート」よりも大幅に高速です。このドキュメントで後述する、より複雑なリロードオプションのいくつかを調査する前に、おそらく試してみるべきです。

詳細については、using-spring-boot.html セクションを参照してください。

15.4. コンテナーを再起動せずに Java クラスをリロードする

最新の IDE(Eclipse、IDEA など)の多くは、バイトコードのホットスワップをサポートしています。クラスまたはメソッドのシグネチャーに影響を与えない変更を加えた場合、副作用なしできれいにリロードする必要があります。

16. ビルド

Spring Boot には、Maven および Gradle のビルドプラグインが含まれています。このセクションでは、これらのプラグインに関する一般的な質問に回答します。

16.1. ビルド情報を生成する

Maven プラグインと Gradle プラグインの両方で、プロジェクトの座標、名前、およびバージョンを含むビルド情報を生成できます。プラグインは、構成によって追加のプロパティを追加するように構成することもできます。そのようなファイルが存在する場合、Spring Boot は BuildProperties Bean を自動構成します。

Maven でビルド情報を生成するには、次の例に示すように、build-info ゴールの実行を追加します。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.3.1.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
詳細については、Spring Boot Maven プラグインのドキュメントを参照してください。

次の例は、Gradle でも同じことを行います。

springBoot {
    buildInfo()
}
詳細については、Spring Boot Gradle プラグインのドキュメントを参照してください。

16.2. Git 情報を生成する

Maven と Gradle の両方により、プロジェクトのビルド時の git ソースコードリポジトリの状態に関する情報を含む git.properties ファイルを生成できます。

Maven ユーザーの場合、spring-boot-starter-parent POM には、git.properties ファイルを生成するための事前構成プラグインが含まれています。それを使用するには、次の宣言を POM に追加します。

<build>
    <plugins>
        <plugin>
            <groupId>pl.project13.maven</groupId>
            <artifactId>git-commit-id-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Gradle ユーザーは、次の例に示すように、gradle-git-properties (英語) プラグインを使用して同じ結果を得ることができます。

plugins {
    id "com.gorylenko.gradle-git-properties" version "2.2.2"
}
git.properties のコミット時間は、次の形式と一致することが予想されます: yyyy-MM-dd’T’HH:mm:ssZ。これは、上記の両方のプラグインのデフォルト形式です。この形式を使用すると、時間を解析して Date に変換し、その形式を JSON に直列化するときに、Jackson の日付の直列化構成設定で制御できます。

16.3. 依存関係バージョンのカスタマイズ

spring-boot-dependencies POM は、一般的な依存関係のバージョンを管理します。Maven および Gradle の Spring Boot プラグインを使用すると、これらのマネージ依存バージョンをビルドプロパティを使用してカスタマイズできます。

各 Spring Boot リリースは、この特定のサードパーティ依存関係セットに対して設計およびテストされています。バージョンを上書きすると、互換性の問題が発生する場合があります。

依存関係バージョンを Maven でオーバーライドするには、Maven プラグインのドキュメントのこのセクションを参照してください。

Gradle の依存バージョンをオーバーライドするには、Gradle プラグインのドキュメントのこのセクションを参照してください。

16.4. Maven を使用して実行可能 JAR を作成する

spring-boot-maven-plugin を使用して、実行可能な「fat 」JAR を作成できます。spring-boot-starter-parent POM を使用する場合、プラグインを宣言でき、jar は次のように再パッケージ化されます。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

親 POM を使用しない場合でも、プラグインを使用できます。ただし、次のように <executions> セクションを追加する必要があります。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.3.1.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

使用方法の詳細については、プラグインのドキュメントを参照してください。

16.5. Spring Boot アプリケーションを依存関係として使用する

war ファイルのように、Spring Boot アプリケーションは依存関係として使用されることを意図していません。アプリケーションに他のプロジェクトと共有するクラスが含まれている場合、推奨されるアプローチは、そのコードを別のモジュールに移動することです。個別のモジュールは、アプリケーションや他のプロジェクトに依存できます。

上記の推奨に従ってコードを再配置できない場合、Spring Boot の Maven および Gradle プラグインは、依存関係としての使用に適した個別のアーティファクトを生成するように構成する必要があります。実行可能 jar 形式は BOOT-INF/classes のアプリケーションクラスをパッケージ化するため、実行可能アーカイブは依存関係として使用できません。つまり、実行可能ファイル jar が依存関係として使用されている場合、それらは見つかりません。

依存関係として使用できるアーティファクトと実行可能なアーティファクトを生成するには、分類子を指定する必要があります。この分類子は、実行可能アーカイブの名前に適用され、デフォルトのアーカイブは依存関係として使用されます。

Maven で exec の分類子を構成するには、次の構成を使用できます。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <classifier>exec</classifier>
            </configuration>
        </plugin>
    </plugins>
</build>

16.6. 実行可能 Jar の実行時に特定のライブラリを抽出する

実行可能 jar のネストされたライブラリのほとんどは、実行するために解凍する必要はありません。ただし、特定のライブラリには問題がある場合があります。例:JRuby には、独自のネストされた jar サポートが含まれています。これは、jruby-complete.jar が常に独自のファイルとして直接利用可能であることを前提としています。

問題のあるライブラリを処理するために、実行可能ファイル jar が最初に実行されるときに、特定のネストされた jar が自動的に解凍されるようにフラグを立てることができます。このようなネストされた jar は、java.io.tmpdir システムプロパティによって識別される一時ディレクトリに書き込まれます。

アプリケーションの実行中に一時ディレクトリに解凍された jar ファイルが削除されないように、オペレーティングシステムが設定されていることを確認する必要があります。

例:Maven プラグインを使用して、JRuby に解凍用のフラグを設定する必要があることを示すには、次の構成を追加します。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <requiresUnpack>
                    <dependency>
                        <groupId>org.jruby</groupId>
                        <artifactId>jruby-complete</artifactId>
                    </dependency>
                </requiresUnpack>
            </configuration>
        </plugin>
    </plugins>
</build>

16.7. 除外付きの非実行可能 JAR を作成する

多くの場合、2 つの別個のビルド製品として実行可能ファイルと実行不可能な jar がある場合、実行可能バージョンにはライブラリ jar で必要のない追加の構成ファイルがあります。例: application.yml 構成ファイルは、実行不可能な JAR から除外される場合があります。

Maven では、実行可能な jar がメインアーティファクトである必要があり、次のように、ライブラリに分類された jar を追加できます。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <id>lib</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <classifier>lib</classifier>
                        <excludes>
                            <exclude>application.yml</exclude>
                        </excludes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

16.8. リモート Maven で開始した Spring Boot アプリケーションのデバッグ

Maven で開始された Spring Boot アプリケーションにリモートデバッガーを接続するには、maven プラグインの jvmArguments プロパティを使用できます。

詳細については、この例を参照してください。

16.9. spring-boot-antlib を使用せずに Ant から実行可能アーカイブを構築する

Ant でビルドするには、依存関係を取得してコンパイルし、jar または war アーカイブを作成する必要があります。実行可能にするには、spring-boot-antlib モジュールを使用するか、次の手順に従います。

  1. jar を構築している場合、ネストされた BOOT-INF/classes ディレクトリにアプリケーションのクラスとリソースをパッケージ化します。war を構築する場合は、通常どおり、ネストされた WEB-INF/classes ディレクトリにアプリケーションのクラスをパッケージ化します。

  2. jar のネストされた BOOT-INF/lib ディレクトリまたは war の WEB-INF/lib にランタイム依存関係を追加します。アーカイブ内のエントリを圧縮しないでください。

  3. jar の場合はネストされた BOOT-INF/lib ディレクトリに、war の場合は WEB-INF/lib-provided に、provided (組み込みコンテナー)依存関係を追加します。アーカイブ内のエントリを圧縮しないでください。

  4. spring-boot-loader クラスをアーカイブのルートに追加します(Main-Class が利用できるように)。

  5. 適切なランチャー(jar ファイルの JarLauncher など)をマニフェストの Main-Class 属性として使用し、必要な他のプロパティをマニフェストエントリとして指定します。主に、Start-Class プロパティを設定します。

次の例は、Ant を使用して実行可能アーカイブを構築する方法を示しています。

<target name="build" depends="compile">
    <jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
        <mappedresources>
            <fileset dir="target/classes" />
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="src/main/resources" erroronmissingdir="false"/>
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="${lib.dir}/runtime" />
            <globmapper from="*" to="BOOT-INF/lib/*"/>
        </mappedresources>
        <zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
        <manifest>
            <attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
            <attribute name="Start-Class" value="${start-class}" />
        </manifest>
    </jar>
</target>

17. 従来のデプロイ

Spring Boot は、従来のデプロイだけでなく、より新しい形式のデプロイもサポートします。このセクションでは、従来のデプロイに関する一般的な質問に回答します。

17.1. デプロイ可能な War ファイルを作成する

Spring WebFlux はサーブレット API に厳密に依存せず、アプリケーションはデフォルトで組み込み Reactor Netty サーバーにデプロイされるため、War デプロイは WebFlux アプリケーションではサポートされていません。

デプロイ可能な war ファイルを作成する最初のステップは、SpringBootServletInitializer サブクラスを提供し、その configure メソッドをオーバーライドすることです。これにより、Spring Framework の Servlet 3.0 サポートが利用され、サーブレットコンテナーによって起動されたときにアプリケーションを設定できます。通常、次の例に示すように、SpringBootServletInitializer を継承するには、アプリケーションのメインクラスを更新する必要があります。

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

次のステップは、プロジェクトが jar ファイルではなく war ファイルを生成するようにビルド構成を更新することです。Maven および spring-boot-starter-parent (Maven の war プラグインを構成する)を使用している場合は、次のように、pom.xml を変更してパッケージを war に変更するだけです。

<packaging>war</packaging>

Gradle を使用する場合は、build.gradle を変更して、war プラグインをプロジェクトに次のように適用する必要があります。

apply plugin: 'war'

プロセスの最後のステップは、組み込みサーブレットコンテナーが war ファイルのデプロイ先のサーブレットコンテナーと干渉しないようにすることです。そのためには、埋め込まれたサーブレットコンテナーの依存関係を提供済みとしてマークする必要があります。

Maven を使用する場合、次の例では、サーブレットコンテナー(この場合は Tomcat)が提供されているとマークします。

<dependencies>
    <!--  …  -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <!--  …  -->
</dependencies>

Gradle を使用する場合、次の例では、サーブレットコンテナー(この場合は Tomcat)が提供されているとマークします。

dependencies {
    //  …
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    //  …
}
providedRuntime は、Gradle の compileOnly 構成よりも優先されます。他の制限の中でも、compileOnly 依存関係はテストクラスパスにないため、Web ベースの統合テストはすべて失敗します。

Spring Boot ビルドツールを使用する場合、組み込みサーブレットコンテナーの依存関係を提供済みとしてマークすると、提供された依存関係が lib-provided ディレクトリにパッケージ化された実行可能な war ファイルが生成されます。つまり、サーブレットコンテナーにデプロイできることに加えて、コマンドラインで java -jar を使用してアプリケーションを実行することもできます。

17.2. 既存のアプリケーションを Spring Boot に変換する

非 Web アプリケーションの場合、既存の Spring アプリケーションを Spring Boot アプリケーションに簡単に変換できるはずです。そのためには、ApplicationContext を作成するコードを破棄し、SpringApplication または SpringApplicationBuilder の呼び出しに置き換えます。Spring MVC Web アプリケーションは、通常、最初にデプロイ可能な war アプリケーションを作成し、それを後で実行可能な war または jar に移行するのに適しています。jar から war への変換に関する入門ガイドを参照してください。

SpringBootServletInitializer を継承して(たとえば Application というクラスに)、Spring Boot @SpringBootApplication アノテーションを追加してデプロイ可能な war を作成するには、次の例に示すようなコードを使用します。

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        // Customize the application or call application.sources(...) to add sources
        // Since our example is itself a @Configuration class (via @SpringBootApplication)
        // we actually don't need to override this method.
        return application;
    }

}

sources に入れるものはすべて Spring ApplicationContext に過ぎないことを忘れないでください。通常、すでに動作しているものはすべてここで動作するはずです。後で削除できる Bean があり、Spring Boot に独自のデフォルトを提供させることもありますが、それを行う前に何かを機能させることができるはずです。

静的リソースは、クラスパスルートの /public (または /static または /resources または /META-INF/resources)に移動できます。同じことが messages.properties (Spring Boot がクラスパスのルートで自動的に検出します)にも当てはまります。

Spring DispatcherServlet および Spring Security のバニラ使用には、それ以上の変更は必要ありません。アプリケーションに他の機能がある場合(たとえば、他のサーブレットやフィルターを使用する場合)、web.xml の要素を次のように置き換えることにより、Application コンテキストに設定を追加する必要がある場合があります。

  • タイプ Servlet または ServletRegistrationBean の @Bean は、あたかも web.xml の <servlet/> および <servlet-mapping/> であるかのように、その Bean をコンテナーにインストールします。

  • タイプ Filter または FilterRegistrationBean の @Bean は、同様に動作します(<filter/> および <filter-mapping/> として)。

  • XML ファイルの ApplicationContext は、Application の @ImportResource を介して追加できます。あるいは、アノテーション構成がすでに頻繁に使用されている単純なケースは、数行で @Bean 定義として再作成できます。

war ファイルが機能したら、次の例に示すように、main メソッドを Application に追加して実行可能にすることができます。

public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}

アプリケーションを war または実行可能アプリケーションとして開始する場合は、SpringBootServletInitializer コールバックと次のようなクラスの main メソッドの両方で使用可能なメソッドでビルダーのカスタマイズを共有する必要があります。

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return configureApplication(builder);
    }

    public static void main(String[] args) {
        configureApplication(new SpringApplicationBuilder()).run(args);
    }

    private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
        return builder.sources(Application.class).bannerMode(Banner.Mode.OFF);
    }

}

アプリケーションは複数のカテゴリに分類できます。

  • web.xml のない Servlet 3.0+ アプリケーション。

  • web.xml を使用したアプリケーション。

  • コンテキスト階層を持つアプリケーション。

  • コンテキスト階層のないアプリケーション。

これらはすべて翻訳に適しているはずですが、それぞれがわずかに異なる技術を必要とする場合があります。

Servlet 3.0+ アプリケーションは、すでに Spring Servlet 3.0+ 初期化子サポートクラスを使用している場合、非常に簡単に変換できます。通常、既存の WebApplicationInitializer からのすべてのコードは SpringBootServletInitializer に移動できます。既存のアプリケーションに複数の ApplicationContext がある場合(たとえば、AbstractDispatcherServletInitializer を使用する場合)、すべてのコンテキストソースを単一の SpringApplication に結合できる場合があります。発生する可能性のある主な問題は、結合が機能せず、コンテキスト階層を維持する必要がある場合です。例については、階層の構築に関するエントリを参照してください。通常、Web 固有の機能を含む既存の親コンテキストは、すべての ServletContextAware コンポーネントが子コンテキストに含まれるように分割する必要があります。

まだ Spring アプリケーションではないアプリケーションは、Spring Boot アプリケーションに変換できる場合があり、前述のガイダンスが役立つ場合があります。ただし、まだ問題が発生する場合があります。その場合は、spring-boot のタグを使用して Stack Overflow で質問する (英語) ことをお勧めします。

17.3. WebLogic への WAR のデプロイ

Spring Boot アプリケーションを WebLogic にデプロイするには、サーブレット初期化子が WebApplicationInitializer を直接実装していることを確認する必要があります(すでに実装している基本クラスから拡張する場合でも)。

WebLogic の一般的な初期化子は、次の例のようになります。

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

}

Logback を使用する場合は、WebLogic に、サーバーにプリインストールされているバージョンではなく、パッケージ化されたバージョンを優先するように指示する必要もあります。これを行うには、次の内容の WEB-INF/weblogic.xml ファイルを追加します。

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
    xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        https://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
        http://xmlns.oracle.com/weblogic/weblogic-web-app
        https://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
    <wls:container-descriptor>
        <wls:prefer-application-packages>
            <wls:package-name>org.slf4j</wls:package-name>
        </wls:prefer-application-packages>
    </wls:container-descriptor>
</wls:weblogic-web-app>

17.4. Lettuce の代わりに Jedis を使用する

デフォルトでは、Spring Boot スターター(spring-boot-starter-data-redis)は Lettuce (GitHub) を使用します。その依存関係を除外し、代わりに Jedis (GitHub) を含める必要があります。Spring Boot はこれらの依存関係を管理して、このプロセスを可能な限り簡単にします。

次の例は、Maven でこれを行う方法を示しています。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

次の例は、Gradle でこれを行う方法を示しています。

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-data-redis') {
        exclude group: 'io.lettuce', module: 'lettuce-core'
    }
    implementation 'redis.clients:jedis'
    // ...
}

17.5. 統合テストに Testcontainers を使用する

テストコンテナー (英語) ライブラリは、Docker コンテナー内で実行されているサービスを管理する方法を提供します。JUnit と統合されているため、テストを実行する前にコンテナーを起動できるテストクラスを作成できます。Testcontainers は、MySQL、MongoDB、Cassandra などの実際のバックエンドサービスと通信する統合テストを作成する場合に特に便利です。テストコンテナーは、次のように Spring Boot テストで使用できます。

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

}

これにより、テストが実行される前に、Neo4j を実行している docker コンテナーが起動します(Docker がローカルで実行されている場合)。ほとんどの場合、コンテナー IP やポートなど、実行中のコンテナーの詳細を使用してアプリケーションを構成する必要があります。

これは、動的なプロパティ値を Spring 環境に追加できる静的 @DynamicPropertySource メソッドで実行できます。

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
    }

}

上記の構成により、アプリケーション内の Neo4j 関連の Bean が、Testcontainers が管理する Docker コンテナー内で実行されている Neo4j と通信できるようになります。

Unofficial Translation by spring.pleiades.io. See the original content.