ほとんどのアプリケーションは、ある時点で入力と出力の問題に対処する必要があります。Spring Boot は、IO 機能が必要な場合に役立つ、ユーティリティとさまざまなテクノロジーとの統合を提供します。このセクションでは、キャッシュや検証などの標準 IO 機能のほか、スケジューリングや分散トランザクションなどのより高度なトピックについて説明します。また、リモート REST または SOAP サービスの呼び出しとメールの送信についても説明します。
1. キャッシング
Spring Framework は、アプリケーションにキャッシュを透過的に追加するためのサポートを提供します。基本的に、抽象化はメソッドにキャッシュを適用するため、キャッシュで利用可能な情報に基づいて実行回数を減らすことができます。キャッシングロジックは、呼び出し側に干渉することなく、透過的に適用されます。Spring Boot は、@EnableCaching アノテーションを使用してキャッシュのサポートが有効になっている限り、キャッシュインフラストラクチャを自動構成します。
| 詳細については、Spring Framework リファレンスの関連セクションを確認してください。 |
簡単に言うと、サービスのオペレーションにキャッシングを追加するには、次の例に示すように、メソッドに関連するアノテーションを追加します。
@Component
public class MyMathService {
@Cacheable("piDecimals")
public int computePiDecimal(int precision) {
...
}
}
@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 は以下のプロバイダーを(示された順序で)検出しようとします。
JCache (JSR-107) (EhCache 3、Hazelcast、Infinispan など)
spring.cache.type プロパティを設定することにより、特定のキャッシュプロバイダーを強制することもできます。特定の環境(テストなど)でキャッシュを完全に無効にする必要がある場合は、このプロパティを使用します。 |
spring-boot-starter-cache 「スターター」を使用して、基本的なキャッシュの依存関係をすばやく追加します。スターターは spring-context-support を持ち込みます。依存関係を手動で追加する場合、JCache または Caffeine サポートを使用するには、spring-context-support を含める必要があります。 |
CacheManager が Spring Boot によって自動構成されている場合は、CacheManagerCustomizer インターフェースを実装する Bean を公開することにより、完全に初期化される前に構成をさらに調整できます。次の例では、null 値を基になるマップに渡してはならないことを示すフラグを設定します。
@Configuration(proxyBeanMethods = false)
public class MyCacheManagerConfiguration {
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
return (cacheManager) -> cacheManager.setAllowNullValues(false);
}
}
@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 は、次の例に示すように、実装の詳細でキャッシュを設定するために最善を尽くします。
# Only necessary if more than one provider is present
spring.cache.jcache.provider=com.example.MyCachingProvider
spring.cache.jcache.config=classpath:example.xml# 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.ConfigurationBean が定義されている場合、それを使用してカスタマイズします。org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizerBean は、完全なカスタマイズのために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 (英語) にはデフォルトの構成ファイルの場所がないため、明示的に指定する必要があります。それ以外の場合、デフォルトのブートストラップが使用されます。
spring.cache.infinispan.config=infinispan.xmlspring:
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 キャッシュが作成されます。
spring.cache.cache-names=cache1,cache2
spring.cache.couchbase.expiration=10mspring:
cache:
cache-names: "cache1,cache2"
couchbase:
expiration: "10m" 構成をさらに制御する必要がある場合は、CouchbaseCacheManagerBuilderCustomizer Bean の登録を検討してください。次の例は、cache1 および cache2 の特定のエントリの有効期限を設定するカスタマイザを示しています。
@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)));
}
}
@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 キャッシュを作成します。
spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=10mspring:
cache:
cache-names: "cache1,cache2"
redis:
time-to-live: "10m" デフォルトでは、2 つの個別のキャッシュが同じキーを使用する場合、Redis に重複するキーがなく、無効な値を返すことができないように、キープレフィックスが追加されます。独自の RedisCacheManager を作成する場合は、この設定を有効にしておくことを強くお勧めします。 |
独自の RedisCacheConfiguration @Bean を追加することにより、デフォルト構成を完全に制御できます。これは、デフォルトの直列化戦略をカスタマイズする必要がある場合に役立ちます。 |
構成をさらに制御する必要がある場合は、RedisCacheManagerBuilderCustomizer Bean の登録を検討してください。次の例は、cache1 および cache2 の特定の存続時間を構成するカスタマイザーを示しています。
@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)));
}
}
@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 プロパティを設定することで作成でき、次のいずれか(示された順序)でカスタマイズできます。
spring.cache.caffeine.specによって定義されたキャッシュ仕様com.github.benmanes.caffeine.cache.CaffeineSpecBean が定義されていますcom.github.benmanes.caffeine.cache.CaffeineBean が定義されています
たとえば、次の構成では、最大サイズが 500 で存続時間が 10 分の cache1 および cache2 キャッシュが作成されます。
spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600sspring:
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 エントリに構成するカスタマイザーを示しています。
@Configuration(proxyBeanMethods = false)
public class MyCache2kDefaultsConfiguration {
@Bean
public Cache2kBuilderCustomizer myCache2kDefaultsCustomizer() {
return (builder) -> builder.entryCapacity(200)
.expireAfterWrite(5, TimeUnit.MINUTES);
}
}
@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 プロパティを次のように設定します。
spring.cache.cache-names=cache1,cache2spring:
cache:
cache-names: "cache1,cache2"そうすると、アプリケーションがリストにないキャッシュを使用する場合、実行時にキャッシュが必要になりますが、起動時は失敗します。これは、宣言されていないキャッシュを使用する場合の「実際の」キャッシュプロバイダーの動作に似ています。
2. Hazelcast
Hazelcast (英語) がクラスパス上にあり、適切な構成が見つかった場合、Spring Boot は、アプリケーションに挿入できる HazelcastInstance を自動構成します。
Spring Boot は、最初に次の構成オプションをチェックしてクライアントの作成を試みます。
com.hazelcast.client.config.ClientConfigBean の存在。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 構成ファイルを指定することもできます。
spring.hazelcast.config=classpath:config/my-hazelcast.xmlspring:
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インスタンスは、JobBuilderAPI を使用して構築できます。Calendar.Trigger: 特定のジョブがいつトリガーされるかを定義します。
デフォルトでは、インメモリ JobStore が使用されます。ただし、次の例に示すように、DataSource Bean がアプリケーションで利用可能であり、それに応じて spring.quartz.job-store-type プロパティが構成されている場合、JDBC ベースのストアを構成できます。
spring.quartz.job-store-type=jdbcspring:
quartz:
job-store-type: "jdbc"JDBC ストアを使用すると、次の例に示すように、起動時にスキーマを初期化できます。
spring.quartz.jdbc.initialize-schema=alwaysspring:
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 も同様の方法で注入できます。
public class MySampleJob extends QuartzJobBean {
// 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);
}
}
class MySampleJob : QuartzJobBean() {
// 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] (英語) を参照してください。
特に、特定のデフォルトのタイムアウト値は無限であり、次の例に示すように、応答しないメールサーバーによってスレッドがブロックされるのを避けるために、これを変更することができます。
spring.mail.properties[mail.smtp.connectiontimeout]=5000
spring.mail.properties[mail.smtp.timeout]=3000
spring.mail.properties[mail.smtp.writetimeout]=5000spring:
mail:
properties:
"[mail.smtp.connectiontimeout]": 5000
"[mail.smtp.timeout]": 3000
"[mail.smtp.writetimeout]": 5000JNDI の既存の Session を使用して JavaMailSender を構成することもできます。
spring.mail.jndi-name=mail/Sessionspring:
mail:
jndi-name: "mail/Session"jndi-name が設定されると、他のすべてのセッション関連の設定よりも優先されます。
5. 検証
Bean 検証 1.1 でサポートされるメソッド検証機能は、JSR-303 実装(Hibernate バリデーターなど)がクラスパス上にある限り、自動的に有効になります。これにより、Bean メソッドに、パラメーターおよび / または戻り値の jakarta.validation 制約をアノテーションできます。このようなアノテーション付きメソッドを持つターゲットクラスには、インライン制約アノテーションを検索するメソッドの型レベルで @Validated アノテーションを付ける必要があります。
たとえば、次のサービスは最初の引数の検証をトリガーし、そのサイズが 8 〜 10 であることを確認します。
@Service
@Validated
public class MyBean {
public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code, Author author) {
return ...
}
}
@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 サービスの呼び出し
アプリケーションがリモート REST サービスを呼び出す場合、Spring Boot は RestTemplate または WebClient を使用してそれを非常に便利にします。
6.1. RestTemplate
アプリケーションからリモート REST サービスを呼び出す必要がある場合は、Spring Framework の RestTemplate (Javadoc) クラスを使用できます。RestTemplate インスタンスは使用する前にカスタマイズする必要があることが多いため、Spring Boot は単一の自動構成 RestTemplate Bean を提供しません。ただし、必要に応じて RestTemplate インスタンスを作成するために使用できる RestTemplateBuilder を自動構成します。自動構成された RestTemplateBuilder は、実用的な HttpMessageConverters が 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);
}
}
@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.1.1. RestTemplate のカスタマイズ
RestTemplate カスタマイズには、カスタマイズの適用範囲に応じて 3 つの主なアプローチがあります。
カスタマイズの範囲をできる限り狭くするには、自動構成された RestTemplateBuilder を挿入し、必要に応じてそのメソッドを呼び出します。各メソッド呼び出しは新しい RestTemplateBuilder インスタンスを返すため、カスタマイズはこのビルダーの使用にのみ影響します。
アプリケーション全体で追加のカスタマイズを行うには、RestTemplateCustomizer Bean を使用します。このような Bean はすべて、自動構成された RestTemplateBuilder に自動的に登録され、それを使用して作成されたすべてのテンプレートに適用されます。
次の例は、192.168.0.5 を除くすべてのホストに対してプロキシの使用を構成するカスタマイザーを示しています。
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);
}
}
}
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 を公開しています。
@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));
}
}
@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.2. WebClient
クラスパスに Spring WebFlux がある場合、WebClient を使用してリモート REST サービスを呼び出すこともできます。RestTemplate と比較して、このクライアントはより関数的で完全にリアクティブです。WebClient の詳細については、Spring Framework ドキュメントの専用のセクションを参照してください。
Spring Boot は、WebClient.Builder を作成して事前構成します。コンポーネントに挿入し、WebClient インスタンスを作成するために使用することを強くお勧めします。Spring Boot は、HTTP リソースを共有したり、サーバーのものと同じ方法でコーデックのセットアップを反映したりするようにビルダーを構成しています(WebFlux HTTP コーデックの自動構成を参照)。
次のコードは典型的な例を示しています。
@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);
}
}
@Service
class MyService(webClientBuilder: WebClient.Builder) {
private val webClient: WebClient
init {
webClient = webClientBuilder.baseUrl("https://example.org").build()
}
fun someRestCall(name: String?): Mono<Relationship.Details> {
return webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(
Relationship.Details::class.java
)
}
}
6.2.1. WebClient ランタイム
Spring Boot は、アプリケーションのクラスパスで使用可能なライブラリに応じて、WebClient を駆動するためにどの ClientHttpConnector を使用するかを自動検出します。現時点では、Reactor、Netty、Jetty、ReactiveStream クライアント、Apache HttpClient、および 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 を定義し、クライアント構成を完全に制御できます。
Spring Framework リファレンスドキュメントの WebClient 構成オプションについて詳しく知ることができます。
6.2.2. WebClient のカスタマイズ
WebClient カスタマイズには、カスタマイズの適用範囲に応じて 3 つの主なアプローチがあります。
カスタマイズの範囲をできる限り狭くするには、自動構成された WebClient.Builder を挿入し、必要に応じてそのメソッドを呼び出します。WebClient.Builder インスタンスはステートフルです: ビルダーでの変更は、その後作成されたすべてのクライアントに反映されます。同じビルダーで複数のクライアントを作成する場合は、WebClient.Builder other = builder.clone(); でビルダーを複製することも検討できます。
アプリケーション全体で、すべての WebClient.Builder インスタンスに追加のカスタマイズを行うには、WebClientCustomizer Bean を宣言し、注入の時点で WebClient.Builder をローカルに変更します。
最後に、元の API にフォールバックして WebClient.create() を使用できます。その場合、自動構成または WebClientCustomizer は適用されません。
7. Web サービス
Spring Boot は Web サービスの自動構成を提供するため、Endpoints を定義するだけです。
Spring Web Services の機能は、spring-boot-starter-webservices モジュールで簡単にアクセスできます。
SimpleWsdl11Definition および SimpleXsdSchema Bean は、それぞれ WSDL および XSD に対して自動的に作成できます。これを行うには、次の例に示すように、場所を構成します。
spring.webservices.wsdl-locations=classpath:/wsdlspring:
webservices:
wsdl-locations: "classpath:/wsdl"7.1. WebServiceTemplate を使用した Web サービスの呼び出し
アプリケーションからリモート Web サービスを呼び出す必要がある場合は、WebServiceTemplate クラスを使用できます。WebServiceTemplate インスタンスは、使用する前にカスタマイズする必要があることが多いため、Spring Boot は単一の自動構成 WebServiceTemplate Bean を提供しません。ただし、必要に応じて WebServiceTemplate インスタンスを作成するために使用できる WebServiceTemplateBuilder を自動構成します。
次のコードは典型的な例を示しています。
@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"));
}
}
@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 を検出します。次のように、読み取りタイムアウトと接続タイムアウトをカスタマイズすることもできます。
@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();
}
}
@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/UserTransaction、java: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 に注入できます。
public MyBean(ConnectionFactory connectionFactory) {
// ...
}
状況によっては、XA 以外の ConnectionFactory を使用して特定の JMS メッセージを処理したい場合があります。例: JMS 処理ロジックは XA タイムアウトよりも長くかかる場合があります。
XA 以外の ConnectionFactory を使用する場合は、nonXaJmsConnectionFactory Bean を使用できます。
public MyBean(@Qualifier("nonXaJmsConnectionFactory") ConnectionFactory connectionFactory) {
// ...
}
一貫性を保つために、jmsConnectionFactory Bean は、Bean エイリアス xaJmsConnectionFactory を使用して提供されます。
public MyBean(@Qualifier("xaJmsConnectionFactory") ConnectionFactory connectionFactory) {
// ...
}
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 がサポートを提供するさまざまなテクノロジについて十分に理解できたはずです。
次のいくつかのセクションでは、クラウドプラットフォームへのアプリケーションのデプロイについて詳しく説明します。次のセクションでコンテナーイメージの構築について読むか、本番環境に対応した機能のセクションにスキップしてください。