ほとんどのアプリケーションは、ある時点で入力と出力の問題に対処する必要があります。Spring Boot は、IO 機能が必要な場合に役立つ、ユーティリティとさまざまなテクノロジーとの統合を提供します。このセクションでは、キャッシュや検証などの標準 IO 機能のほか、スケジューリングや分散トランザクションなどのより高度なトピックについて説明します。また、リモート REST または SOAP サービスの呼び出しとメールの送信についても説明します。

1. キャッシング

Spring Framework は、アプリケーションにキャッシュを透過的に追加するためのサポートを提供します。基本的に、抽象化はメソッドにキャッシュを適用するため、キャッシュで利用可能な情報に基づいて実行回数を減らすことができます。キャッシングロジックは、呼び出し側に干渉することなく、透過的に適用されます。Spring Boot は、@EnableCaching アノテーションを使用してキャッシュのサポートが有効になっている限り、キャッシュインフラストラクチャを自動構成します。

詳細については、Spring Framework リファレンスの関連セクションを確認してください。

簡単に言うと、サービスのオペレーションにキャッシングを追加するには、次の例に示すように、メソッドに関連するアノテーションを追加します。

Java
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class MyMathService {

    @Cacheable("piDecimals")
    public int computePiDecimal(int precision) {
        ...
    }

}
Kotlin
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Component

@Component
class MyMathService {

    @Cacheable("piDecimals")
    fun computePiDecimal(precision: Int): Int {
        ...
    }

}

この例は、潜在的にコストのかかる操作でのキャッシュの使用を示しています。computePiDecimal を呼び出す前に、抽象化は i 引数に一致する piDecimals キャッシュ内のエントリを探します。エントリが見つかった場合、キャッシュ内のコンテンツはすぐに呼び出し元に返され、メソッドは呼び出されません。それ以外の場合、メソッドが呼び出され、値を返す前にキャッシュが更新されます。

標準の JSR-107(JCache)アノテーション(@CacheResult など)を透過的に使用することもできます。ただし、Spring Cache アノテーションと JCache アノテーションを混在させないでください。

特定のキャッシュライブラリを追加しない場合、Spring Boot はメモリ内の同時マップを使用する単純なプロバイダーを自動構成します。キャッシュが必要な場合(前の例の piDecimals など)、このプロバイダーがキャッシュを作成します。単純なプロバイダーは、本番環境での使用にはあまりお勧めしませんが、使い始めて、機能を理解していることを確認するには最適です。使用するキャッシュプロバイダーについて決めたら、必ずそのドキュメントを読んで、アプリケーションが使用するキャッシュを構成する方法を理解しましょう。ほぼすべてのプロバイダーでは、アプリケーションで使用するすべてのキャッシュを明示的に構成する必要があります。spring.cache.cache-names プロパティで定義されたデフォルトのキャッシュをカスタマイズする方法を提供するものもあります。

キャッシュからデータを透過的に更新または削除することもできます。

1.1. サポートされているキャッシュプロバイダー

キャッシュ抽象化は実際のストアを提供せず、org.springframework.cache.Cache および org.springframework.cache.CacheManager インターフェースによって具体化される抽象化に依存します。

型 CacheManager の Bean または cacheResolver という名前の CacheResolver を定義していない場合(CachingConfigurer (Javadoc) を参照)、Spring Boot は以下のプロバイダーを(示された順序で)検出しようとします。

CacheManager が Spring Boot によって自動構成されている場合は、spring.cache.type プロパティを設定することで特定のキャッシュプロバイダーを強制できます。特定の環境 (テストなど) で no-op キャッシュを使用する必要がある場合は、このプロパティを使用します。
spring-boot-starter-cache 「スターター」を使用して、基本的なキャッシュの依存関係をすばやく追加します。スターターは spring-context-support を持ち込みます。依存関係を手動で追加する場合、JCache または Caffeine サポートを使用するには、spring-context-support を含める必要があります。

CacheManager が Spring Boot によって自動構成されている場合は、CacheManagerCustomizer インターフェースを実装する Bean を公開することにより、完全に初期化される前に構成をさらに調整できます。次の例では、null 値を基になるマップに渡してはならないことを示すフラグを設定します。

Java
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyCacheManagerConfiguration {

    @Bean
    public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
        return (cacheManager) -> cacheManager.setAllowNullValues(false);
    }

}
Kotlin
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer
import org.springframework.cache.concurrent.ConcurrentMapCacheManager
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyCacheManagerConfiguration {

    @Bean
    fun cacheManagerCustomizer(): CacheManagerCustomizer<ConcurrentMapCacheManager> {
        return CacheManagerCustomizer { cacheManager ->
            cacheManager.isAllowNullValues = false
        }
    }

}
上記の例では、自動構成された ConcurrentMapCacheManager が予期されています。そうでない場合(独自の構成を提供したか、別のキャッシュプロバイダーが自動構成された場合)、カスタマイザーはまったく呼び出されません。カスタマイザーは必要な数だけ持つことができ、@Order または Ordered を使用してオーダーすることもできます。

1.1.1. 汎用

コンテキストが少なくとも 1 つの org.springframework.cache.Cache Bean を定義している場合、汎用キャッシングが使用されます。その型のすべての Bean をラップする CacheManager が作成されます。

1.1.2. JCache (JSR-107)

JCache (英語) は、クラスパスに javax.cache.spi.CachingProvider が存在することでブートストラップされ(つまり、JSR-107 準拠のキャッシュライブラリがクラスパスに存在します)、JCacheCacheManager は spring-boot-starter-cache 「スターター」によって提供されます。さまざまな準拠ライブラリが利用可能であり、Spring Boot は Ehcache 3、Hazelcast、Infinispan の依存関係管理を提供します。他の準拠ライブラリも追加できます。

複数のプロバイダーが存在する場合がありますが、その場合はプロバイダーを明示的に指定する必要があります。JSR-107 標準が構成ファイルの場所を定義する標準化された方法を強制しない場合でも、Spring Boot は、次の例に示すように、実装の詳細でキャッシュを設定するために最善を尽くします。

Properties
# Only necessary if more than one provider is present
spring.cache.jcache.provider=com.example.MyCachingProvider
spring.cache.jcache.config=classpath:example.xml
Yaml
# Only necessary if more than one provider is present
spring:
  cache:
    jcache:
      provider: "com.example.MyCachingProvider"
      config: "classpath:example.xml"
キャッシュライブラリがネイティブ実装と JSR-107 サポートの両方を提供する場合、Spring Boot は JSR-107 サポートを優先するため、別の JSR-107 実装に切り替えると同じ機能を使用できます。
Spring Boot は Hazelcast を一般的にサポートしています。単一の HazelcastInstance が使用可能な場合、spring.cache.jcache.config プロパティが指定されていない限り、CacheManager にも自動的に再利用されます。

基になる javax.cache.cacheManager をカスタマイズするには、2 つの方法があります。

  • spring.cache.cache-names プロパティを設定することにより、起動時にキャッシュを作成できます。カスタム javax.cache.configuration.Configuration Bean が定義されている場合、それを使用してカスタマイズします。

  • org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer Bean は、完全なカスタマイズのために CacheManager を参照して呼び出されます。

標準 javax.cache.CacheManager Bean が定義されている場合、抽象化が期待する org.springframework.cache.CacheManager 実装で自動的にラップされます。それ以上のカスタマイズは適用されません。

1.1.3. Hazelcast

Spring Boot は Hazelcast を一般的にサポートしていますHazelcastInstance が自動構成され、com.hazelcast:hazelcast-spring がクラスパス上にある場合、CacheManager に自動的にラップされます。

Hazelcast は、JCache 準拠のキャッシュとして、または Spring CacheManager 準拠のキャッシュとして使用できます。spring.cache.type を hazelcast に設定すると、Spring Boot は CacheManager ベースの実装を使用します。Hazelcast を JCache 準拠のキャッシュとして使用する場合は、spring.cache.type を jcache に設定します。複数の JCache 準拠のキャッシュプロバイダーがあり、強制的に Hazelcast を使用する場合は、JCache プロバイダーを明示的に設定する必要があります。

1.1.4. Infinispan

Infinispan (英語) にはデフォルトの構成ファイルの場所がないため、明示的に指定する必要があります。それ以外の場合、デフォルトのブートストラップが使用されます。

Properties
spring.cache.infinispan.config=infinispan.xml
Yaml
spring:
  cache:
    infinispan:
      config: "infinispan.xml"

spring.cache.cache-names プロパティを設定することにより、起動時にキャッシュを作成できます。カスタム ConfigurationBuilder Bean が定義されている場合、それを使用してキャッシュをカスタマイズします。

Spring Boot の Jakarta EE 9 ベースラインと互換性を持たせるには、Infinispan の -jakarta モジュールを使用する必要があります。-jakarta バリアントを持つすべてのモジュールについて、そのバリアントを標準モジュールの代わりに使用する必要があります。例: infinispan-core および infinispan-commons の代わりに、それぞれ infinispan-core-jakarta および infinispan-commons-jakarta を使用する必要があります。

1.1.5. Couchbase

Spring Data Couchbase が使用可能で、Couchbase が構成されている場合、CouchbaseCacheManager が自動構成されます。spring.cache.cache-names プロパティを設定することにより、起動時に追加のキャッシュを作成することが可能で、spring.cache.couchbase.* プロパティを使用してキャッシュのデフォルトを構成できます。たとえば、次の構成では、エントリの有効期限が 10 分の cache1 および cache2 キャッシュが作成されます。

Properties
spring.cache.cache-names=cache1,cache2
spring.cache.couchbase.expiration=10m
Yaml
spring:
  cache:
    cache-names: "cache1,cache2"
    couchbase:
      expiration: "10m"

構成をさらに制御する必要がある場合は、CouchbaseCacheManagerBuilderCustomizer Bean の登録を検討してください。次の例は、cache1 および cache2 の特定のエントリの有効期限を設定するカスタマイザを示しています。

Java
import java.time.Duration;

import org.springframework.boot.autoconfigure.cache.CouchbaseCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.cache.CouchbaseCacheConfiguration;

@Configuration(proxyBeanMethods = false)
public class MyCouchbaseCacheManagerConfiguration {

    @Bean
    public CouchbaseCacheManagerBuilderCustomizer myCouchbaseCacheManagerBuilderCustomizer() {
        return (builder) -> builder
                .withCacheConfiguration("cache1", CouchbaseCacheConfiguration
                        .defaultCacheConfig().entryExpiry(Duration.ofSeconds(10)))
                .withCacheConfiguration("cache2", CouchbaseCacheConfiguration
                        .defaultCacheConfig().entryExpiry(Duration.ofMinutes(1)));

    }

}
Kotlin
import org.springframework.boot.autoconfigure.cache.CouchbaseCacheManagerBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.couchbase.cache.CouchbaseCacheConfiguration
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyCouchbaseCacheManagerConfiguration {

    @Bean
    fun myCouchbaseCacheManagerBuilderCustomizer(): CouchbaseCacheManagerBuilderCustomizer {
        return CouchbaseCacheManagerBuilderCustomizer { builder ->
            builder
                .withCacheConfiguration(
                    "cache1", CouchbaseCacheConfiguration
                        .defaultCacheConfig().entryExpiry(Duration.ofSeconds(10))
                )
                .withCacheConfiguration(
                    "cache2", CouchbaseCacheConfiguration
                        .defaultCacheConfig().entryExpiry(Duration.ofMinutes(1))
                )
        }
    }

}

1.1.6. Redis

Redis (英語) が使用可能で構成されている場合、RedisCacheManager は自動構成されます。spring.cache.cache-names プロパティを設定することにより、起動時に追加のキャッシュを作成でき、spring.cache.redis.* プロパティを使用してキャッシュのデフォルトを設定できます。たとえば、次の構成では、存続時間 10 分で cache1 および cache2 キャッシュを作成します。

Properties
spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=10m
Yaml
spring:
  cache:
    cache-names: "cache1,cache2"
    redis:
      time-to-live: "10m"
デフォルトでは、2 つの個別のキャッシュが同じキーを使用する場合、Redis に重複するキーがなく、無効な値を返すことができないように、キープレフィックスが追加されます。独自の RedisCacheManager を作成する場合は、この設定を有効にしておくことを強くお勧めします。
独自の RedisCacheConfiguration@Bean を追加することにより、デフォルト構成を完全に制御できます。これは、デフォルトの直列化戦略をカスタマイズする必要がある場合に役立ちます。

構成をさらに制御する必要がある場合は、RedisCacheManagerBuilderCustomizer Bean の登録を検討してください。次の例は、cache1 および cache2 の特定の存続時間を構成するカスタマイザーを示しています。

Java
import java.time.Duration;

import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;

@Configuration(proxyBeanMethods = false)
public class MyRedisCacheManagerConfiguration {

    @Bean
    public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() {
        return (builder) -> builder
                .withCacheConfiguration("cache1", RedisCacheConfiguration
                        .defaultCacheConfig().entryTtl(Duration.ofSeconds(10)))
                .withCacheConfiguration("cache2", RedisCacheConfiguration
                        .defaultCacheConfig().entryTtl(Duration.ofMinutes(1)));

    }

}
Kotlin
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.cache.RedisCacheConfiguration
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyRedisCacheManagerConfiguration {

    @Bean
    fun myRedisCacheManagerBuilderCustomizer(): RedisCacheManagerBuilderCustomizer {
        return RedisCacheManagerBuilderCustomizer { builder ->
            builder
                .withCacheConfiguration(
                    "cache1", RedisCacheConfiguration
                        .defaultCacheConfig().entryTtl(Duration.ofSeconds(10))
                )
                .withCacheConfiguration(
                    "cache2", RedisCacheConfiguration
                        .defaultCacheConfig().entryTtl(Duration.ofMinutes(1))
                )
        }
    }

}

1.1.7. Caffeine

Caffeine [GitHub] (英語) は、Guava のサポートに代わる Guava のキャッシュの Java 8 の書き換えです。Caffeine が存在する場合、CaffeineCacheManager (spring-boot-starter-cache 「スターター」によって提供される)が自動構成されます。キャッシュは、起動時に spring.cache.cache-names プロパティを設定することで作成でき、次のいずれか(示された順序)でカスタマイズできます。

  1. spring.cache.caffeine.spec によって定義されたキャッシュ仕様

  2. com.github.benmanes.caffeine.cache.CaffeineSpec Bean が定義されています

  3. com.github.benmanes.caffeine.cache.Caffeine Bean が定義されています

たとえば、次の構成では、最大サイズが 500 で存続時間が 10 分の cache1 および cache2 キャッシュが作成されます。

Properties
spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
Yaml
spring:
  cache:
    cache-names: "cache1,cache2"
    caffeine:
      spec: "maximumSize=500,expireAfterAccess=600s"

com.github.benmanes.caffeine.cache.CacheLoader Bean が定義されている場合、CaffeineCacheManager に自動的に関連付けられます。CacheLoader はキャッシュマネージャーによって管理されるすべてのキャッシュに関連付けられるため、CacheLoader<Object, Object> として定義する必要があります。自動構成では、他の一般的な型は無視されます。

1.1.8. Cache2k

Cache2k (英語) はメモリ内キャッシュです。Cache2kSpring 統合が存在する場合、SpringCache2kCacheManager は自動構成されます。

spring.cache.cache-names プロパティを設定することにより、起動時にキャッシュを作成できます。キャッシュのデフォルトは、Cache2kBuilderCustomizer Bean を使用してカスタマイズできます。次の例は、キャッシュの容量を 5 分の有効期限で 200 エントリに構成するカスタマイザーを示しています。

Java
import java.util.concurrent.TimeUnit;

import org.springframework.boot.autoconfigure.cache.Cache2kBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyCache2kDefaultsConfiguration {

    @Bean
    public Cache2kBuilderCustomizer myCache2kDefaultsCustomizer() {
        return (builder) -> builder.entryCapacity(200)
                .expireAfterWrite(5, TimeUnit.MINUTES);
    }

}
Kotlin
import org.springframework.boot.autoconfigure.cache.Cache2kBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.concurrent.TimeUnit

@Configuration(proxyBeanMethods = false)
class MyCache2kDefaultsConfiguration {

    @Bean
    fun myCache2kDefaultsCustomizer(): Cache2kBuilderCustomizer {
        return Cache2kBuilderCustomizer { builder ->
            builder.entryCapacity(200)
                .expireAfterWrite(5, TimeUnit.MINUTES)
        }
    }
}

1.1.9. シンプル

他のプロバイダーが見つからない場合は、ConcurrentHashMap をキャッシュストアとして使用する単純な実装が構成されます。アプリケーションにキャッシングライブラリが存在しない場合、これがデフォルトです。デフォルトでは、キャッシュは必要に応じて作成されますが、cache-names プロパティを設定することにより、使用可能なキャッシュのリストを制限できます。たとえば、cache1 および cache2 キャッシュのみが必要な場合は、cache-names プロパティを次のように設定します。

Properties
spring.cache.cache-names=cache1,cache2
Yaml
spring:
  cache:
    cache-names: "cache1,cache2"

そうすると、アプリケーションがリストにないキャッシュを使用する場合、実行時にキャッシュが必要になりますが、起動時は失敗します。これは、宣言されていないキャッシュを使用する場合の「実際の」キャッシュプロバイダーの動作に似ています。

1.1.10. なし

構成に @EnableCaching が存在する場合、適切なキャッシュ構成も期待されます。カスタム CacheManager がある場合は、必要に応じてオーバーライドできるように、それを別の @Configuration クラスで定義することを検討してください。None はテストに役立つ no-op 実装を使用し、スライステストはデフォルトで @AutoConfigureCache 経由でそれを使用します。

特定の環境で自動構成キャッシュマネージャーではなく no-op キャッシュを使用する必要がある場合は、次の例に示すように、キャッシュ型を none に設定します。

Properties
spring.cache.type=none
Yaml
spring:
  cache:
    type: "none"

2. Hazelcast

Hazelcast (英語) がクラスパス上にあり、適切な構成が見つかった場合、Spring Boot は、アプリケーションに挿入できる HazelcastInstance を自動構成します。

Spring Boot は、最初に次の構成オプションをチェックしてクライアントの作成を試みます。

  • com.hazelcast.client.config.ClientConfig Bean の存在。

  • spring.hazelcast.config プロパティによって定義された構成ファイル。

  • hazelcast.client.config システムプロパティの存在。

  • 作業ディレクトリまたはクラスパスのルートにある hazelcast-client.xml

  • 作業ディレクトリまたはクラスパスのルートにある hazelcast-client.yaml (または hazelcast-client.yml)。

クライアントを作成できない場合、Spring Boot は組み込みサーバーの構成を試みます。com.hazelcast.config.Config Bean を定義する場合、Spring Boot はそれを使用します。構成でインスタンス名が定義されている場合、Spring Boot は、新しいインスタンスを作成するのではなく、既存のインスタンスを見つけようとします。

次の例に示すように、構成を通じて使用する Hazelcast 構成ファイルを指定することもできます。

Properties
spring.hazelcast.config=classpath:config/my-hazelcast.xml
Yaml
spring:
  hazelcast:
    config: "classpath:config/my-hazelcast.xml"

それ以外の場合、Spring Boot は、デフォルトの場所 (作業ディレクトリまたはクラスパスのルートにある hazelcast.xml、または同じ場所にある YAML 相当物) から Hazelcast 構成を検索しようとします。hazelcast.config システムプロパティが設定されているかどうかも確認します。詳細については、Hazelcast ドキュメント (英語) を参照してください。

デフォルトでは、Hazelcast コンポーネントの @SpringAware がサポートされています。ManagementContext は、ゼロより大きい @Order を持つ HazelcastConfigCustomizer Bean を宣言することによってオーバーライドできます。
Spring Boot には、Hazelcast の明示的なキャッシュサポートもあります。キャッシュが有効になっている場合、HazelcastInstance は CacheManager 実装に自動的にラップされます。

3. Quartz スケジューラー

Spring Boot は、spring-boot-starter-quartz 「スターター」を含む、Quartz スケジューラー (英語) を操作するためのいくつかの便利な機能を提供します。Quartz が使用可能な場合、Scheduler は(SchedulerFactoryBean 抽象化により)自動構成されます。

次の型の Bean が自動的に取得され、Scheduler に関連付けられます。

  • JobDetail: 特定のジョブを定義します。JobDetail インスタンスは、JobBuilder API を使用して構築できます。

  • Calendar.

  • Trigger: 特定のジョブがいつトリガーされるかを定義します。

デフォルトでは、インメモリ JobStore が使用されます。ただし、次の例に示すように、DataSource Bean がアプリケーションで利用可能であり、それに応じて spring.quartz.job-store-type プロパティが構成されている場合、JDBC ベースのストアを構成できます。

Properties
spring.quartz.job-store-type=jdbc
Yaml
spring:
  quartz:
    job-store-type: "jdbc"

JDBC ストアを使用すると、次の例に示すように、起動時にスキーマを初期化できます。

Properties
spring.quartz.jdbc.initialize-schema=always
Yaml
spring:
  quartz:
    jdbc:
      initialize-schema: "always"
デフォルトでは、Quartz ライブラリで提供される標準スクリプトを使用して、データベースが検出および初期化されます。これらのスクリプトは既存のテーブルを削除し、再起動するたびにすべてのトリガーを削除します。spring.quartz.jdbc.schema プロパティを設定して、カスタムスクリプトを提供することもできます。

Quartz でアプリケーションのメイン DataSource 以外の DataSource を使用するには、DataSource Bean を宣言し、@Bean メソッドに @QuartzDataSource アノテーションを付けます。そうすることで、Quartz 固有の DataSource が SchedulerFactoryBean とスキーマの初期化の両方で使用されるようになります。同様に、Quartz にアプリケーションのメイン TransactionManager 以外の TransactionManager を使用させるには、TransactionManager Bean を宣言し、@Bean メソッドに @QuartzTransactionManager アノテーションを付けます。

デフォルトでは、構成によって作成されたジョブは、永続ジョブストアから読み取られた登録済みのジョブを上書きしません。既存のジョブ定義の上書きを有効にするには、spring.quartz.overwrite-existing-jobs プロパティを設定します。

Quartz スケジューラー構成は、spring.quartz プロパティおよび SchedulerFactoryBeanCustomizer Bean を使用してカスタマイズできます。これにより、プログラムによる SchedulerFactoryBean のカスタマイズが可能になります。spring.quartz.properties.* を使用して、高度な Quartz 構成プロパティをカスタマイズできます。

特に、Quartz は spring.quartz.properties を介してスケジューラーを構成する方法を提供するため、Executor Bean はスケジューラーに関連付けられていません。タスクエグゼキュータをカスタマイズする必要がある場合は、SchedulerFactoryBeanCustomizer の実装を検討してください。

ジョブは、setter を定義してデータマッププロパティを挿入できます。次の例に示すように、通常の Bean も同様の方法で注入できます。

Java
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import org.springframework.scheduling.quartz.QuartzJobBean;

public class MySampleJob extends QuartzJobBean {

    // fields ...

    private MyService myService;

    private String name;

    // Inject "MyService" bean
    public void setMyService(MyService myService) {
        this.myService = myService;
    }

    // Inject the "name" job data property
    public void setName(String name) {
        this.name = name;
    }

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        this.myService.someMethod(context.getFireTime(), this.name);
    }

}
Kotlin
import org.quartz.JobExecutionContext
import org.springframework.scheduling.quartz.QuartzJobBean

class MySampleJob : QuartzJobBean() {

    // fields ...

    private var myService: MyService? = null

    private var name: String? = null

    // Inject "MyService" bean
    fun setMyService(myService: MyService?) {
        this.myService = myService
    }

    // Inject the "name" job data property
    fun setName(name: String?) {
        this.name = name
    }

    override fun executeInternal(context: JobExecutionContext) {
        myService!!.someMethod(context.fireTime, name)
    }

}

4. メール送信

Spring Framework は、JavaMailSender インターフェースを使用してメールを送信するための抽象化を提供し、Spring Boot は、自動構成とスターターモジュールを提供します。

JavaMailSender の使用方法の詳細については、リファレンスドキュメントを参照してください。

spring.mail.host および関連するライブラリ(spring-boot-starter-mail で定義されている)が使用可能な場合、存在しない場合はデフォルトの JavaMailSender が作成されます。送信者は、spring.mail 名前空間の構成アイテムによってさらにカスタマイズできます。詳細については、MailProperties [GitHub] (英語) を参照してください。

特に、特定のデフォルトのタイムアウト値は無限であり、次の例に示すように、応答しないメールサーバーによってスレッドがブロックされるのを避けるために、これを変更することができます。

Properties
spring.mail.properties[mail.smtp.connectiontimeout]=5000
spring.mail.properties[mail.smtp.timeout]=3000
spring.mail.properties[mail.smtp.writetimeout]=5000
Yaml
spring:
  mail:
    properties:
      "[mail.smtp.connectiontimeout]": 5000
      "[mail.smtp.timeout]": 3000
      "[mail.smtp.writetimeout]": 5000

JNDI の既存の Session を使用して JavaMailSender を構成することもできます。

Properties
spring.mail.jndi-name=mail/Session
Yaml
spring:
  mail:
    jndi-name: "mail/Session"

jndi-name が設定されると、他のすべてのセッション関連の設定よりも優先されます。

5. 検証

Bean 検証 1.1 でサポートされるメソッド検証機能は、JSR-303 実装(Hibernate バリデーターなど)がクラスパス上にある限り、自動的に有効になります。これにより、Bean メソッドに、パラメーターおよび / または戻り値の jakarta.validation 制約をアノテーションできます。このようなアノテーション付きメソッドを持つターゲットクラスには、インライン制約アノテーションを検索するメソッドの型レベルで @Validated アノテーションを付ける必要があります。

たとえば、次のサービスは最初の引数の検証をトリガーし、そのサイズが 8 〜 10 であることを確認します。

Java
import jakarta.validation.constraints.Size;

import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

@Service
@Validated
public class MyBean {

    public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code, Author author) {
        return ...
    }

}
Kotlin
import jakarta.validation.constraints.Size
import org.springframework.stereotype.Service
import org.springframework.validation.annotation.Validated

@Service
@Validated
class MyBean {

    fun findByCodeAndAuthor(code: @Size(min = 8, max = 10) String?, author: Author?): Archive? {
        return null
    }

}

アプリケーションの MessageSource は、制約メッセージの {parameters} を解決するときに使用されます。これにより、アプリケーションの messages.properties ファイルを Bean 検証メッセージに使用できます。パラメーターが解決されると、Bean バリデーションのデフォルトの補間器を使用してメッセージの補間が完了します。

ValidatorFactory の作成に使用される Configuration をカスタマイズするには、ValidationConfigurationCustomizer Bean を定義します。複数のカスタマイザ Bean が定義されている場合、@Order アノテーションまたは Ordered 実装に基づいて順番に呼び出されます。

6. REST サービスの呼び出し

Spring Boot は、リモート REST サービスを呼び出すためのさまざまな便利な方法を提供します。ノンブロッキングのリアクティブアプリケーションを開発していて、Spring WebFlux を使用している場合は、WebClient を使用できます。API をブロックしたい場合は、RestClient または RestTemplate を使用できます。

6.1. WebClient

クラスパスに Spring WebFlux がある場合は、WebClient を使用して リモート REST サービスを呼び出すことをお勧めします。WebClient インターフェースは関数型 API を提供し、完全にリアクティブです。WebClient の詳細については、Spring Framework ドキュメントの専用セクションを参照してください。

リアクティブ Spring WebFlux アプリケーションを作成していない場合は、WebClient の代わりに RestClient を使用できます。これは同様の機能の API を提供しますが、リアクティブではなくブロッキングです。

Spring Boot は、プロトタイプ WebClient.Builder Bean を作成し、事前構成します。これをコンポーネントに挿入し、それを使用して WebClient インスタンスを作成することを強くお勧めします。Spring Boot は、HTTP リソースを共有し、サーバーのものと同じ方法でコーデックのセットアップを反映するようにそのビルダーを構成しています (WebFlux HTTP コーデックの自動構成を参照)。

次のコードは典型的な例を示しています。

Java
import reactor.core.publisher.Mono;

import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

@Service
public class MyService {

    private final WebClient webClient;

    public MyService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.baseUrl("https://example.org").build();
    }

    public Mono<Details> someRestCall(String name) {
        return this.webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(Details.class);
    }

}
Kotlin
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono

@Service
class MyService(webClientBuilder: WebClient.Builder) {

    private val webClient: WebClient

    init {
        webClient = webClientBuilder.baseUrl("https://example.org").build()
    }

    fun someRestCall(name: String?): Mono<Details> {
        return webClient.get().uri("/{name}/details", name)
                .retrieve().bodyToMono(Details::class.java)
    }

}

6.1.1. WebClient ランタイム

Spring Boot は、アプリケーションのクラスパスで利用可能なライブラリに応じて、WebClient の駆動にどの ClientHttpConnector を使用するかを自動検出します。優先順位に従って、次のクライアントがサポートされます。

  1. Reactor Netty

  2. Jetty RS クライアント

  3. Apache HttpClient

  4. JDK HttpClient

クラスパス上で複数のクライアントが使用可能な場合は、最も優先されるクライアントが使用されます。

spring-boot-starter-webflux スターターは、デフォルトで io.projectreactor.netty:reactor-netty に依存しており、サーバーとクライアントの両方の実装をもたらします。代わりにリアクティブサーバーとして Jetty を使用することを選択した場合は、Jetty リアクティブ HTTP クライアントライブラリ org.eclipse.jetty:jetty-reactive-httpclient への依存関係を追加する必要があります。サーバーとクライアントに同じテクノロジーを使用すると、クライアントとサーバー間で HTTP リソースが自動的に共有されるため、利点があります。

開発者は、カスタム ReactorResourceFactory または JettyResourceFactory Bean を提供することにより、Jetty および Reactor Netty のリソース構成をオーバーライドできます。これは、クライアントとサーバーの両方に適用されます。

クライアントのその選択をオーバーライドする場合は、独自の ClientHttpConnector Bean を定義し、クライアント構成を完全に制御できます。

6.1.2. WebClient のカスタマイズ

WebClient カスタマイズには、カスタマイズの適用範囲に応じて 3 つの主なアプローチがあります。

カスタマイズの範囲をできる限り狭くするには、自動構成された WebClient.Builder を挿入し、必要に応じてそのメソッドを呼び出します。WebClient.Builder インスタンスはステートフルです: ビルダーでの変更は、その後作成されたすべてのクライアントに反映されます。同じビルダーで複数のクライアントを作成する場合は、WebClient.Builder other = builder.clone(); でビルダーを複製することも検討できます。

アプリケーション全体で、すべての WebClient.Builder インスタンスに追加のカスタマイズを行うには、WebClientCustomizer Bean を宣言し、注入の時点で WebClient.Builder をローカルに変更します。

最後に、元の API にフォールバックして WebClient.create() を使用できます。その場合、自動構成または WebClientCustomizer は適用されません。

6.1.3. WebClient SSL サポート

WebClient で使用される ClientHttpConnector でカスタム SSL 構成が必要な場合は、ビルダーの apply メソッドで使用できる WebClientSsl インスタンスを挿入できます。

WebClientSsl インターフェースは、application.properties または application.yaml ファイルで定義した任意の SSL バンドルへのアクセスを提供します。

次のコードは典型的な例を示しています。

Java
import reactor.core.publisher.Mono;

import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientSsl;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

@Service
public class MyService {

    private final WebClient webClient;

    public MyService(WebClient.Builder webClientBuilder, WebClientSsl ssl) {
        this.webClient = webClientBuilder.baseUrl("https://example.org").apply(ssl.fromBundle("mybundle")).build();
    }

    public Mono<Details> someRestCall(String name) {
        return this.webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(Details.class);
    }

}
Kotlin
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientSsl
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono

@Service
class MyService(webClientBuilder: WebClient.Builder, ssl: WebClientSsl) {

    private val webClient: WebClient

    init {
        webClient = webClientBuilder.baseUrl("https://example.org")
                .apply(ssl.fromBundle("mybundle")).build()
    }

    fun someRestCall(name: String?): Mono<Details> {
        return webClient.get().uri("/{name}/details", name)
                .retrieve().bodyToMono(Details::class.java)
    }

}

6.2. RestClient

アプリケーションで Spring WebFlux またはプロジェクト Reactor を使用していない場合は、RestClient を使用して リモート REST サービスを呼び出すことをお勧めします。

RestClient インターフェースは、関数型スタイルのブロッキング API を提供します。

Spring Boot は、プロトタイプ RestClient.Builder Bean を作成し、事前構成します。これをコンポーネントに挿入し、それを使用して RestClient インスタンスを作成することを強くお勧めします。Spring Boot は、そのビルダーを HttpMessageConverters および適切な ClientHttpRequestFactory で構成しています。

次のコードは典型的な例を示しています。

Java
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;

@Service
public class MyService {

    private final RestClient restClient;

    public MyService(RestClient.Builder restClientBuilder) {
        this.restClient = restClientBuilder.baseUrl("https://example.org").build();
    }

    public Details someRestCall(String name) {
        return this.restClient.get().uri("/{name}/details", name).retrieve().body(Details.class);
    }

}
Kotlin
import org.springframework.boot.docs.io.restclient.restclient.ssl.Details
import org.springframework.stereotype.Service
import org.springframework.web.client.RestClient

@Service
class MyService(restClientBuilder: RestClient.Builder) {

    private val restClient: RestClient

    init {
        restClient = restClientBuilder.baseUrl("https://example.org").build()
    }

    fun someRestCall(name: String?): Details {
        return restClient.get().uri("/{name}/details", name)
                .retrieve().body(Details::class.java)!!
    }

}

6.2.1. RestClient のカスタマイズ

RestClient カスタマイズには、カスタマイズの適用範囲に応じて 3 つの主なアプローチがあります。

カスタマイズの範囲をできる限り狭くするには、自動構成された RestClient.Builder を挿入し、必要に応じてそのメソッドを呼び出します。RestClient.Builder インスタンスはステートフルです: ビルダーでの変更は、その後作成されたすべてのクライアントに反映されます。同じビルダーで複数のクライアントを作成する場合は、RestClient.Builder other = builder.clone(); でビルダーを複製することも検討できます。

アプリケーション全体で、すべての RestClient.Builder インスタンスに追加のカスタマイズを行うには、RestClientCustomizer Bean を宣言し、注入の時点で RestClient.Builder をローカルに変更します。

最後に、元の API にフォールバックして RestClient.create() を使用できます。その場合、自動構成または RestClientCustomizer は適用されません。

6.2.2. RestClient SSL サポート

RestClient で使用される ClientHttpRequestFactory でカスタム SSL 構成が必要な場合は、ビルダーの apply メソッドで使用できる RestClientSsl インスタンスを挿入できます。

RestClientSsl インターフェースは、application.properties または application.yaml ファイルで定義した任意の SSL バンドルへのアクセスを提供します。

次のコードは典型的な例を示しています。

Java
import org.springframework.boot.autoconfigure.web.client.RestClientSsl;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;

@Service
public class MyService {

    private final RestClient restClient;

    public MyService(RestClient.Builder restClientBuilder, RestClientSsl ssl) {
        this.restClient = restClientBuilder.baseUrl("https://example.org").apply(ssl.fromBundle("mybundle")).build();
    }

    public Details someRestCall(String name) {
        return this.restClient.get().uri("/{name}/details", name).retrieve().body(Details.class);
    }

}
Kotlin
import org.springframework.boot.autoconfigure.web.client.RestClientSsl
import org.springframework.boot.docs.io.restclient.restclient.ssl.settings.Details
import org.springframework.stereotype.Service
import org.springframework.web.client.RestClient

@Service
class MyService(restClientBuilder: RestClient.Builder, ssl: RestClientSsl) {

    private val restClient: RestClient

    init {
        restClient = restClientBuilder.baseUrl("https://example.org")
                .apply(ssl.fromBundle("mybundle")).build()
    }

    fun someRestCall(name: String?): Details {
        return restClient.get().uri("/{name}/details", name)
                .retrieve().body(Details::class.java)!!
    }

}

SSL バンドルに加えて他のカスタマイズを適用する必要がある場合は、ClientHttpRequestFactorySettings クラスを ClientHttpRequestFactories とともに使用できます。

Java
import java.time.Duration;

import org.springframework.boot.ssl.SslBundles;
import org.springframework.boot.web.client.ClientHttpRequestFactories;
import org.springframework.boot.web.client.ClientHttpRequestFactorySettings;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;

@Service
public class MyService {

    private final RestClient restClient;

    public MyService(RestClient.Builder restClientBuilder, SslBundles sslBundles) {
        ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.DEFAULTS
            .withReadTimeout(Duration.ofMinutes(2))
            .withSslBundle(sslBundles.getBundle("mybundle"));
        ClientHttpRequestFactory requestFactory = ClientHttpRequestFactories.get(settings);
        this.restClient = restClientBuilder.baseUrl("https://example.org").requestFactory(requestFactory).build();
    }

    public Details someRestCall(String name) {
        return this.restClient.get().uri("/{name}/details", name).retrieve().body(Details.class);
    }

}
Kotlin
import org.springframework.boot.ssl.SslBundles
import org.springframework.boot.web.client.ClientHttpRequestFactories
import org.springframework.boot.web.client.ClientHttpRequestFactorySettings
import org.springframework.stereotype.Service
import org.springframework.web.client.RestClient
import java.time.Duration

@Service
class MyService(restClientBuilder: RestClient.Builder, sslBundles: SslBundles) {

    private val restClient: RestClient

    init {
        val settings = ClientHttpRequestFactorySettings.DEFAULTS
                .withReadTimeout(Duration.ofMinutes(2))
                .withSslBundle(sslBundles.getBundle("mybundle"))
        val requestFactory = ClientHttpRequestFactories.get(settings)
        restClient = restClientBuilder
                .baseUrl("https://example.org")
                .requestFactory(requestFactory).build()
    }

    fun someRestCall(name: String?): Details {
        return restClient.get().uri("/{name}/details", name).retrieve().body(Details::class.java)!!
    }

}

6.3. RestTemplate

Spring Framework の RestTemplate (Javadoc) クラスは RestClient よりも前から存在し、多くのアプリケーションが リモート REST サービスを呼び出すために使用する典型的な方法です。RestClient に移行したくない既存のコードがある場合、または RestTemplate API にすでに慣れている場合は、RestTemplate の使用を選択することもできます。

RestTemplate インスタンスは使用前にカスタマイズする必要があることが多いため、Spring Boot には単一の自動構成 RestTemplate Bean が提供されていません。ただし、RestTemplateBuilder は自動構成され、必要に応じて RestTemplate インスタンスの作成に使用できます。自動構成された RestTemplateBuilder により、適切な HttpMessageConverters と適切な ClientHttpRequestFactory が RestTemplate インスタンスに適用されます。

次のコードは典型的な例を示しています。

Java
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class MyService {

    private final RestTemplate restTemplate;

    public MyService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    public Details someRestCall(String name) {
        return this.restTemplate.getForObject("/{name}/details", Details.class, name);
    }

}
Kotlin
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate

@Service
class MyService(restTemplateBuilder: RestTemplateBuilder) {

    private val restTemplate: RestTemplate

    init {
        restTemplate = restTemplateBuilder.build()
    }

    fun someRestCall(name: String): Details {
        return restTemplate.getForObject("/{name}/details", Details::class.java, name)!!
    }

}

RestTemplateBuilder には、RestTemplate を迅速に構成するために使用できる便利なメソッドが多数含まれています。例: BASIC 認証サポートを追加するには、builder.basicAuthentication("user", "password").build() を使用できます。

6.3.1. RestTemplate のカスタマイズ

RestTemplate カスタマイズには、カスタマイズの適用範囲に応じて 3 つの主なアプローチがあります。

カスタマイズの範囲をできる限り狭くするには、自動構成された RestTemplateBuilder を挿入し、必要に応じてそのメソッドを呼び出します。各メソッド呼び出しは新しい RestTemplateBuilder インスタンスを返すため、カスタマイズはこのビルダーの使用にのみ影響します。

アプリケーション全体で追加のカスタマイズを行うには、RestTemplateCustomizer Bean を使用します。このような Bean はすべて、自動構成された RestTemplateBuilder に自動的に登録され、それを使用して作成されたすべてのテンプレートに適用されます。

次の例は、192.168.0.5 を除くすべてのホストに対してプロキシの使用を構成するカスタマイザーを示しています。

Java
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
import org.apache.hc.client5.http.routing.HttpRoutePlanner;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.protocol.HttpContext;

import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

public class MyRestTemplateCustomizer implements RestTemplateCustomizer {

    @Override
    public void customize(RestTemplate restTemplate) {
        HttpRoutePlanner routePlanner = new CustomRoutePlanner(new HttpHost("proxy.example.com"));
        HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build();
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
    }

    static class CustomRoutePlanner extends DefaultProxyRoutePlanner {

        CustomRoutePlanner(HttpHost proxy) {
            super(proxy);
        }

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

    }

}
Kotlin
import org.apache.hc.client5.http.classic.HttpClient
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner
import org.apache.hc.client5.http.routing.HttpRoutePlanner
import org.apache.hc.core5.http.HttpException
import org.apache.hc.core5.http.HttpHost
import org.apache.hc.core5.http.protocol.HttpContext
import org.springframework.boot.web.client.RestTemplateCustomizer
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.client.RestTemplate

class MyRestTemplateCustomizer : RestTemplateCustomizer {

    override fun customize(restTemplate: RestTemplate) {
        val routePlanner: HttpRoutePlanner = CustomRoutePlanner(HttpHost("proxy.example.com"))
        val httpClient: HttpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build()
        restTemplate.requestFactory = HttpComponentsClientHttpRequestFactory(httpClient)
    }

    internal class CustomRoutePlanner(proxy: HttpHost?) : DefaultProxyRoutePlanner(proxy) {

        @Throws(HttpException::class)
        public override fun determineProxy(target: HttpHost, context: HttpContext): HttpHost? {
            if (target.hostName == "192.168.0.5") {
                return null
            }
            return  super.determineProxy(target, context)
        }

    }

}

最後に、独自の RestTemplateBuilder Bean を定義できます。そうすることで、自動構成されたビルダーが置き換えられます。自動構成の場合と同様に、RestTemplateCustomizer Bean をカスタムビルダーに適用する場合は、RestTemplateBuilderConfigurer を使用して構成します。次の例では、カスタム接続と読み取りのタイムアウトも指定されていることを除いて、Spring Boot の自動構成が実行したものと一致する RestTemplateBuilder を公開しています。

Java
import java.time.Duration;

import org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyRestTemplateBuilderConfiguration {

    @Bean
    public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) {
        return configurer.configure(new RestTemplateBuilder())
            .setConnectTimeout(Duration.ofSeconds(5))
            .setReadTimeout(Duration.ofSeconds(2));
    }

}
Kotlin
import org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyRestTemplateBuilderConfiguration {

    @Bean
    fun restTemplateBuilder(configurer: RestTemplateBuilderConfigurer): RestTemplateBuilder {
        return configurer.configure(RestTemplateBuilder()).setConnectTimeout(Duration.ofSeconds(5))
            .setReadTimeout(Duration.ofSeconds(2))
    }

}

最も極端な(そしてめったに使用されない)オプションは、コンフィギュレーターを使用せずに独自の RestTemplateBuilder Bean を作成することです。自動構成されたビルダーを置き換えるだけでなく、これにより RestTemplateCustomizer Bean が使用されなくなります。

6.3.2. RestTemplate SSL サポート

RestTemplate でカスタム SSL 構成が必要な場合は、次の例に示すように SSL バンドルを RestTemplateBuilder に適用できます。

Java
import org.springframework.boot.docs.io.restclient.resttemplate.Details;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class MyService {

    private final RestTemplate restTemplate;

    public MyService(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
        this.restTemplate = restTemplateBuilder.setSslBundle(sslBundles.getBundle("mybundle")).build();
    }

    public Details someRestCall(String name) {
        return this.restTemplate.getForObject("/{name}/details", Details.class, name);
    }

}
Kotlin
import org.springframework.boot.docs.io.restclient.resttemplate.Details
import org.springframework.boot.ssl.SslBundles
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate

@Service
class MyService(restTemplateBuilder: RestTemplateBuilder, sslBundles: SslBundles) {

    private val restTemplate: RestTemplate

    init {
        restTemplate = restTemplateBuilder.setSslBundle(sslBundles.getBundle("mybundle")).build()
    }

    fun someRestCall(name: String): Details {
        return restTemplate.getForObject("/{name}/details", Details::class.java, name)!!
    }

}

6.4. RestClient および RestTemplate の HTTP クライアントの検出

Spring Boot は、アプリケーションのクラスパスで使用可能なライブラリに応じて、RestClient および RestTemplate で使用する HTTP クライアントを自動検出します。優先順位に従って、次のクライアントがサポートされます。

  1. Apache HttpClient

  2. Jetty HttpClient

  3. OkHttp (非推奨)

  4. シンプルな JDK クライアント (HttpURLConnection)

クラスパス上で複数のクライアントが使用可能な場合は、最も優先されるクライアントが使用されます。

7. Web サービス

Spring Boot は Web サービスの自動構成を提供するため、Endpoints を定義するだけです。

Spring Web Services の機能は、spring-boot-starter-webservices モジュールで簡単にアクセスできます。

SimpleWsdl11Definition および SimpleXsdSchema Bean は、それぞれ WSDL および XSD に対して自動的に作成できます。これを行うには、次の例に示すように、場所を構成します。

Properties
spring.webservices.wsdl-locations=classpath:/wsdl
Yaml
spring:
  webservices:
    wsdl-locations: "classpath:/wsdl"

7.1. WebServiceTemplate を使用した Web サービスの呼び出し

アプリケーションからリモート Web サービスを呼び出す必要がある場合は、WebServiceTemplate クラスを使用できます。WebServiceTemplate インスタンスは、使用する前にカスタマイズする必要があることが多いため、Spring Boot は単一の自動構成 WebServiceTemplate Bean を提供しません。ただし、必要に応じて WebServiceTemplate インスタンスを作成するために使用できる WebServiceTemplateBuilder を自動構成します。

次のコードは典型的な例を示しています。

Java
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.client.core.SoapActionCallback;

@Service
public class MyService {

    private final WebServiceTemplate webServiceTemplate;

    public MyService(WebServiceTemplateBuilder webServiceTemplateBuilder) {
        this.webServiceTemplate = webServiceTemplateBuilder.build();
    }

    public SomeResponse someWsCall(SomeRequest detailsReq) {
        return (SomeResponse) this.webServiceTemplate.marshalSendAndReceive(detailsReq,
                new SoapActionCallback("https://ws.example.com/action"));
    }

}
Kotlin
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder
import org.springframework.stereotype.Service
import org.springframework.ws.client.core.WebServiceTemplate
import org.springframework.ws.soap.client.core.SoapActionCallback

@Service
class MyService(webServiceTemplateBuilder: WebServiceTemplateBuilder) {

    private val webServiceTemplate: WebServiceTemplate

    init {
        webServiceTemplate = webServiceTemplateBuilder.build()
    }

    fun someWsCall(detailsReq: SomeRequest?): SomeResponse {
        return webServiceTemplate.marshalSendAndReceive(
            detailsReq,
            SoapActionCallback("https://ws.example.com/action")
        ) as SomeResponse
    }

}

デフォルトでは、WebServiceTemplateBuilder は、クラスパスで使用可能な HTTP クライアントライブラリを使用して、適切な HTTP ベースの WebServiceMessageSender を検出します。次のように、読み取りタイムアウトと接続タイムアウトをカスタマイズすることもできます。

Java
import java.time.Duration;

import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder;
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.WebServiceMessageSender;

@Configuration(proxyBeanMethods = false)
public class MyWebServiceTemplateConfiguration {

    @Bean
    public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) {
        WebServiceMessageSender sender = new HttpWebServiceMessageSenderBuilder()
                .setConnectTimeout(Duration.ofSeconds(5))
                .setReadTimeout(Duration.ofSeconds(2))
                .build();
        return builder.messageSenders(sender).build();
    }

}
Kotlin
import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.ws.client.core.WebServiceTemplate
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyWebServiceTemplateConfiguration {

    @Bean
    fun webServiceTemplate(builder: WebServiceTemplateBuilder): WebServiceTemplate {
        val sender = HttpWebServiceMessageSenderBuilder()
            .setConnectTimeout(Duration.ofSeconds(5))
            .setReadTimeout(Duration.ofSeconds(2))
            .build()
        return builder.messageSenders(sender).build()
    }

}

8. JTA による分散トランザクション

Spring Boot は、JNDI から取得したトランザクションマネージャーを使用して、複数の XA リソースに分散された JTA トランザクションをサポートします。

JTA 環境が検出されると、Spring の JtaTransactionManager を使用してトランザクションが管理されます。自動構成された JMS、DataSource、JPA Bean は、XA トランザクションをサポートするためにアップグレードされます。@Transactional などの標準的な Spring イディオムを使用して、分散トランザクションに参加できます。JTA 環境内でローカルトランザクションを使用する場合は、spring.jta.enabled プロパティを false に設定して、JTA 自動構成を無効にすることができます。

8.1. Jakarta EE Managed Transaction Manager を使用する

Spring Boot アプリケーションを war または ear ファイルとしてパッケージ化し、それを Jakarta EE アプリケーションサーバーにデプロイする場合は、アプリケーションサーバーの組み込みのトランザクションマネージャーを使用できます。Spring Boot は、一般的な JNDI ロケーション(java:comp/UserTransactionjava:comp/TransactionManager など)を調べて、トランザクションマネージャーを自動構成しようとします。アプリケーションサーバーが提供するトランザクションサービスを使用する場合は、通常、すべてのリソースがサーバーによって管理され、JNDI を介して公開されるようにする必要があります。Spring Boot は、JNDI パス(java:/JmsXA または java:/XAConnectionFactory)で ConnectionFactory を探すことによって JMS を自動構成しようとします。また、spring.datasource.jndi-name プロパティを使用して DataSource を構成できます。

8.2. XA と非 XA JMS 接続の混在

JTA を使用する場合、プライマリ JMS ConnectionFactory Bean は XA 対応であり、分散トランザクションに参加します。@Qualifier を使用せずに Bean に注入できます。

Java
public MyBean(ConnectionFactory connectionFactory) {
    // ...
}
Kotlin

状況によっては、XA 以外の ConnectionFactory を使用して特定の JMS メッセージを処理したい場合があります。例: JMS 処理ロジックは XA タイムアウトよりも長くかかる場合があります。

XA 以外の ConnectionFactory を使用する場合は、nonXaJmsConnectionFactory Bean を使用できます。

Java
public MyBean(@Qualifier("nonXaJmsConnectionFactory") ConnectionFactory connectionFactory) {
    // ...
}
Kotlin

一貫性を保つために、jmsConnectionFactory Bean は、Bean エイリアス xaJmsConnectionFactory を使用して提供されます。

Java
public MyBean(@Qualifier("xaJmsConnectionFactory") ConnectionFactory connectionFactory) {
    // ...
}
Kotlin

8.3. 組み込みトランザクションマネージャーのサポート

XAConnectionFactoryWrapper [GitHub] (英語) および XADataSourceWrapper [GitHub] (英語) インターフェースは、組み込みトランザクションマネージャーをサポートするために使用できます。インターフェースは、XAConnectionFactory および XADataSource Bean をラップし、通常の ConnectionFactory および DataSource Bean として公開し、分散トランザクションに透過的に登録します。JtaTransactionManager Bean と適切な XA ラッパー Bean が ApplicationContext 内に登録されている場合、DataSource および JMS 自動構成は JTA バリアントを使用します。

9. 次のステップ

これで、Spring Boot のコア機能と、自動構成によって Spring Boot がサポートを提供するさまざまなテクノロジについて十分に理解できたはずです。

次のいくつかのセクションでは、クラウドプラットフォームへのアプリケーションのデプロイについて詳しく説明します。次のセクションでコンテナーイメージの構築について読むか、本番環境に対応した機能のセクションにスキップしてください。