ほとんどのアプリケーションは、ある時点で入力と出力の問題に対処する必要があります。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 など)
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
値を基になるマップに渡してはならないことを示すフラグを設定します。
@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.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 (英語) にはデフォルトの構成ファイルの場所がないため、明示的に指定する必要があります。それ以外の場合、デフォルトのブートストラップが使用されます。
spring.cache.infinispan.config=infinispan.xml
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
キャッシュが作成されます。
spring.cache.cache-names=cache1,cache2
spring.cache.couchbase.expiration=10m
spring:
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=10m
spring:
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.CaffeineSpec
Bean が定義されていますcom.github.benmanes.caffeine.cache.Caffeine
Bean が定義されています
たとえば、次の構成では、最大サイズが 500 で存続時間が 10 分の cache1
および cache2
キャッシュが作成されます。
spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
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 エントリに構成するカスタマイザーを示しています。
@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,cache2
spring:
cache:
cache-names: "cache1,cache2"
そうすると、アプリケーションがリストにないキャッシュを使用する場合、実行時にキャッシュが必要になりますが、起動時は失敗します。これは、宣言されていないキャッシュを使用する場合の「実際の」キャッシュプロバイダーの動作に似ています。
1.1.10. なし
構成に @EnableCaching
が存在する場合、適切なキャッシュ構成も期待されます。カスタム CacheManager
がある場合は、必要に応じてオーバーライドできるように、それを別の @Configuration
クラスで定義することを検討してください。None はテストに役立つ no-op 実装を使用し、スライステストはデフォルトで @AutoConfigureCache
経由でそれを使用します。
特定の環境で自動構成キャッシュマネージャーではなく no-op キャッシュを使用する必要がある場合は、次の例に示すように、キャッシュ型を none
に設定します。
spring.cache.type=none
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 構成ファイルを指定することもできます。
spring.hazelcast.config=classpath:config/my-hazelcast.xml
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 ベースのストアを構成できます。
spring.quartz.job-store-type=jdbc
spring:
quartz:
job-store-type: "jdbc"
JDBC ストアを使用すると、次の例に示すように、起動時にスキーマを初期化できます。
spring.quartz.jdbc.initialize-schema=always
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 も同様の方法で注入できます。
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]=5000
spring:
mail:
properties:
"[mail.smtp.connectiontimeout]": 5000
"[mail.smtp.timeout]": 3000
"[mail.smtp.writetimeout]": 5000
JNDI の既存の Session
を使用して JavaMailSender
を構成することもできます。
spring.mail.jndi-name=mail/Session
spring:
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 サービスの呼び出し
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 コーデックの自動構成を参照)。
次のコードは典型的な例を示しています。
@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<Details> {
return webClient.get().uri("/{name}/details", name)
.retrieve().bodyToMono(Details::class.java)
}
}
6.1.1. WebClient ランタイム
Spring Boot は、アプリケーションのクラスパスで利用可能なライブラリに応じて、WebClient
の駆動にどの ClientHttpConnector
を使用するかを自動検出します。優先順位に従って、次のクライアントがサポートされます。
Reactor Netty
Jetty RS クライアント
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.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 バンドルへのアクセスを提供します。
次のコードは典型的な例を示しています。
@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);
}
}
@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
で構成しています。
次のコードは典型的な例を示しています。
@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);
}
}
@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 バンドルへのアクセスを提供します。
次のコードは典型的な例を示しています。
@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);
}
}
@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
とともに使用できます。
@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);
}
}
@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
インスタンスに適用されます。
次のコードは典型的な例を示しています。
@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.3.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.3.2. RestTemplate SSL サポート
RestTemplate
でカスタム SSL 構成が必要な場合は、次の例に示すように SSL バンドルを RestTemplateBuilder
に適用できます。
@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);
}
}
@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 クライアントを自動検出します。優先順位に従って、次のクライアントがサポートされます。
Apache HttpClient
Jetty HttpClient
OkHttp (非推奨)
シンプルな JDK クライアント (
HttpURLConnection
)
クラスパス上で複数のクライアントが使用可能な場合は、最も優先されるクライアントが使用されます。
7. Web サービス
Spring Boot は Web サービスの自動構成を提供するため、Endpoints
を定義するだけです。
Spring Web Services の機能は、spring-boot-starter-webservices
モジュールで簡単にアクセスできます。
SimpleWsdl11Definition
および SimpleXsdSchema
Bean は、それぞれ WSDL および XSD に対して自動的に作成できます。これを行うには、次の例に示すように、場所を構成します。
spring.webservices.wsdl-locations=classpath:/wsdl
spring:
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 がサポートを提供するさまざまなテクノロジについて十分に理解できたはずです。
次のいくつかのセクションでは、クラウドプラットフォームへのアプリケーションのデプロイについて詳しく説明します。次のセクションでコンテナーイメージの構築について読むか、本番環境に対応した機能のセクションにスキップしてください。