Spring Boot は、Web アプリケーションの開発に最適です。組み込み Tomcat、Jetty、Undertow、Netty を使用して、自己完結型の HTTP サーバーを作成できます。ほとんどの Web アプリケーションは、spring-boot-starter-web
モジュールを使用して、すばやく起動して実行します。spring-boot-starter-webflux
モジュールを使用して、リアクティブ Web アプリケーションを構築することもできます。
Spring Boot Web アプリケーションをまだ開発していない場合は、入門セクションの "Hello World!" の例に従うことができます。
1. サーブレット Web アプリケーション
サーブレットベースの Web アプリケーションを構築する場合は、Spring MVC または Jersey 用の Spring Boot の自動構成を利用できます。
1.1. 「Spring Web MVC フレームワーク」
Spring Web MVC フレームワーク ( "Spring MVC" と呼ばれることが多い) は、リッチな「モデル、ビュー、コントローラー」Web フレームワークです。Spring MVC を使用すると、受信 HTTP リクエストを処理するための特別な @Controller
または @RestController
Bean を作成できます。コントローラーのメソッドは、@RequestMapping
アノテーションを使用して HTTP にマップされます。
次のコードは、JSON データを提供する典型的な @RestController
を示しています。
@RestController
@RequestMapping("/users")
public class MyRestController {
private final UserRepository userRepository;
private final CustomerRepository customerRepository;
public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {
this.userRepository = userRepository;
this.customerRepository = customerRepository;
}
@GetMapping("/{user}")
public User getUser(@PathVariable Long userId) {
return this.userRepository.findById(userId).get();
}
@GetMapping("/{user}/customers")
public List<Customer> getUserCustomers(@PathVariable Long userId) {
return this.userRepository.findById(userId).map(this.customerRepository::findByUser).get();
}
@DeleteMapping("/{user}")
public void deleteUser(@PathVariable Long userId) {
this.userRepository.deleteById(userId);
}
}
Spring MVC はコア Spring Framework の一部であり、詳細情報はリファレンスドキュメントで入手できます。spring.io/guides で入手可能な Spring MVC をカバーするガイドもいくつかあります。
1.1.1. Spring MVC 自動構成
Spring Boot は、ほとんどのアプリケーションでうまく機能する Spring MVC の自動構成を提供します。
自動構成により、Spring のデフォルトに加えて次の機能が追加されます。
ContentNegotiatingViewResolver
およびBeanNameViewResolver
Bean の包含。WebJars のサポートを含む静的リソースの提供のサポート(このドキュメントの後半で説明します)。
Converter
、GenericConverter
、Formatter
Bean の自動登録。HttpMessageConverters
のサポート(このドキュメントで後述)。MessageCodesResolver
の自動登録(このドキュメントで後述)。静的
index.html
サポート。ConfigurableWebBindingInitializer
Bean の自動使用(このドキュメントで後述)。
これらの Spring Boot MVC のカスタマイズを保持し、さらに MVC のカスタマイズ(インターセプター、フォーマッター、View Controller、およびその他の機能)を作成する場合は、@EnableWebMvc
なしで型 WebMvcConfigurer
の独自の @Configuration
クラスを追加できます。
RequestMappingHandlerMapping
、RequestMappingHandlerAdapter
、ExceptionHandlerExceptionResolver
のカスタムインスタンスを提供し、それでも Spring Boot MVC のカスタマイズを維持したい場合は、型 WebMvcRegistrations
の Bean を宣言し、それを使用してこれらのコンポーネントのカスタムインスタンスを提供できます。
Spring MVC を完全に制御したい場合は、@EnableWebMvc
でアノテーションを付けた独自の @Configuration
を追加するか、@EnableWebMvc
の Javadoc に従って、独自の @Configuration
アノテーション付き DelegatingWebMvcConfiguration
を追加できます。
Spring MVC は、 Spring MVC が使用する |
1.1.2. HttpMessageConverters
Spring MVC は、HttpMessageConverter
インターフェースを使用して HTTP リクエストとレスポンスを変換します。適切なデフォルトは、すぐに含まれています。例: オブジェクトは、JSON (Jackson ライブラリを使用) または XML (使用可能な場合は Jackson XML 拡張を使用するか、Jackson XML 拡張が使用できない場合は JAXB を使用) に自動的に変換できます。デフォルトでは、文字列は UTF-8
でエンコードされます。
コンバーターを追加またはカスタマイズする必要がある場合は、次のように、Spring Boot の HttpMessageConverters
クラスを使用できます。
@Configuration(proxyBeanMethods = false)
public class MyHttpMessageConvertersConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter();
HttpMessageConverter<?> another = new AnotherHttpMessageConverter();
return new HttpMessageConverters(additional, another);
}
}
コンテキストに存在する HttpMessageConverter
Bean は、コンバーターのリストに追加されます。同じ方法でデフォルトのコンバーターをオーバーライドすることもできます。
1.1.3. カスタム JSON シリアライザーとデシリアライザー
Jackson を使用して JSON データをシリアライズおよびデシリアライズする場合、独自の JsonSerializer
および JsonDeserializer
クラスを作成することができます。カスタムシリアライザーは通常、モジュールを介して Jackson に登録されます [GitHub] (英語) が、Spring Boot は Spring Bean を直接登録しやすくする代替 @JsonComponent
アノテーションを提供します。
JsonSerializer
、JsonDeserializer
または KeyDeserializer
実装で @JsonComponent
アノテーションを直接使用できます。次の例に示すように、内部クラスとしてシリアライザー / デシリアライザーを含むクラスでも使用できます。
@JsonComponent
public class MyJsonComponent {
public static class Serializer extends JsonSerializer<MyObject> {
@Override
public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
}
}
public static class Deserializer extends JsonDeserializer<MyObject> {
@Override
public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectCodec codec = jsonParser.getCodec();
JsonNode tree = codec.readTree(jsonParser);
String name = tree.get("name").textValue();
int age = tree.get("age").intValue();
return new MyObject(name, age);
}
}
}
ApplicationContext
内のすべての @JsonComponent
Bean は、Jackson に自動的に登録されます。@JsonComponent
は @Component
でメタアノテーションが付けられているため、通常のコンポーネントスキャンルールが適用されます。
Spring Boot は、オブジェクトを直列化するときに標準 Jackson バージョンの有用な代替を提供する JsonObjectSerializer
[GitHub] (英語) および JsonObjectDeserializer
[GitHub] (英語) 基本クラスも提供します。詳細については、Javadoc の JsonObjectSerializer
(Javadoc) および JsonObjectDeserializer
(Javadoc) を参照してください。
上記の例は、JsonObjectSerializer
/JsonObjectDeserializer
を使用するように次のように書き直すことができます。
@JsonComponent
public class MyJsonComponent {
public static class Serializer extends JsonObjectSerializer<MyObject> {
@Override
protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
}
}
public static class Deserializer extends JsonObjectDeserializer<MyObject> {
@Override
protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
JsonNode tree) throws IOException {
String name = nullSafeValue(tree.get("name"), String.class);
int age = nullSafeValue(tree.get("age"), Integer.class);
return new MyObject(name, age);
}
}
}
1.1.4. MessageCodesResolver
Spring MVC には、バインディングエラーからエラーメッセージをレンダリングするためのエラーコードを生成するための戦略があります: MessageCodesResolver
。spring.mvc.message-codes-resolver-format
プロパティ PREFIX_ERROR_CODE
または POSTFIX_ERROR_CODE
を設定すると、Spring Boot によって作成されます ( DefaultMessageCodesResolver.Format
(Javadoc) の列挙を参照)。
1.1.5. 静的コンテンツ
デフォルトでは、Spring Boot は、クラスパス内の /static
(または /public
または /resources
または /META-INF/resources
) というディレクトリから、または ServletContext
のルートから静的コンテンツを提供します。Spring MVC の ResourceHttpRequestHandler
を使用しているため、独自の WebMvcConfigurer
を追加して addResourceHandlers
メソッドをオーバーライドすることで、その動作を変更できます。
スタンドアロン Web アプリケーションでは、コンテナーからのデフォルトサーブレットも有効になり、フォールバックとして機能し、Spring が処理しないことを決定した場合、ServletContext
のルートからコンテンツを提供します。Spring は常に DispatcherServlet
を介してリクエストを処理できるため、ほとんどの場合、これは起こりません(デフォルトの MVC 構成を変更しない限り)。
デフォルトでは、リソースは /**
にマップされますが、spring.mvc.static-path-pattern
プロパティでそれを調整できます。たとえば、すべてのリソースを /resources/**
に再配置するには、次のようにします。
spring.mvc.static-path-pattern=/resources/**
spring:
mvc:
static-path-pattern: "/resources/**"
spring.web.resources.static-locations
プロパティを使用して静的リソースの場所をカスタマイズすることもできます(デフォルト値をディレクトリの場所のリストに置き換えます)。ルートサーブレットコンテキストパス "/"
も、場所として自動的に追加されます。
前述の「標準」の静的リソースの場所に加えて、Webjars コンテンツ (英語) には特別なケースが作成されます。WebZZ 形式でパッケージ化されている場合、/webjars/**
にパスを持つリソースは jar ファイルから提供されます。
アプリケーションが jar としてパッケージ化されている場合は、src/main/webapp ディレクトリを使用しないでください。このディレクトリは一般的な標準ですが、war パッケージでのみ機能し、jar を生成する場合、ほとんどのビルドツールでは暗黙のうちに無視されます。 |
Spring Boot は、Spring MVC が提供する高度なリソース処理機能もサポートし、静的リソースのキャッシュ無効化や Webjar のバージョンに依存しない URL の使用などのユースケースを可能にします。
Webjar にバージョンに依存しない URL を使用するには、webjars-locator-core
依存関係を追加します。次に、Webjar を宣言します。例として jQuery を使用して、"/webjars/jquery/jquery.min.js"
を追加すると、"/webjars/jquery/x.y.z/jquery.min.js"
が生成されます(x.y.z
は Webjar バージョンです)。
JBoss を使用する場合、webjars-locator-core ではなく webjars-locator-jboss-vfs 依存関係を宣言する必要があります。それ以外の場合、すべての Webjar は 404 として解決されます。 |
キャッシュ無効化を使用するには、次の構成ですべての静的リソースのキャッシュ無効化ソリューションを構成し、URL に <link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
などのコンテンツハッシュを効果的に追加します。
spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**
spring:
web:
resources:
chain:
strategy:
content:
enabled: true
paths: "/**"
リソースへのリンクは、Thymeleaf および FreeMarker 用に自動構成された ResourceUrlEncodingFilter のおかげで、実行時にテンプレートで書き換えられます。JSP を使用する場合は、このフィルターを手動で宣言する必要があります。現在、他のテンプレートエンジンは自動的にサポートされていませんが、カスタムテンプレートマクロ / ヘルパーおよび ResourceUrlProvider (Javadoc) を使用することができます。 |
JavaScript モジュールローダーなどを使用してリソースを動的にロードする場合、ファイルの名前を変更することはできません。そのため、他の戦略もサポートされており、組み合わせることができます。"fixed" 戦略では、次の例に示すように、ファイル名を変更せずに URL に静的バージョン文字列を追加します。
spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**
spring.web.resources.chain.strategy.fixed.enabled=true
spring.web.resources.chain.strategy.fixed.paths=/js/lib/
spring.web.resources.chain.strategy.fixed.version=v12
spring:
web:
resources:
chain:
strategy:
content:
enabled: true
paths: "/**"
fixed:
enabled: true
paths: "/js/lib/"
version: "v12"
この構成では、"/js/lib/"
にある JavaScript モジュールは固定バージョン管理戦略("/v12/js/lib/mymodule.js"
)を使用しますが、他のリソースはコンテンツコンテンツ(<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
)を引き続き使用します。
サポートされるオプションの詳細については、WebProperties.Resources
[GitHub] (英語) を参照してください。
この機能は、専用のブログ投稿 (英語) および Spring Framework のリファレンスドキュメントで詳細に説明されています。 |
1.1.6. ウェルカムページ
Spring Boot は、静的なウェルカムページとテンプレート化されたウェルカムページの両方をサポートしています。最初に、構成された静的コンテンツの場所で index.html
ファイルを探します。見つからない場合は、index
テンプレートを探します。どちらかが見つかった場合、アプリケーションのウェルカムページとして自動的に使用されます。
1.1.7. パスマッチングとコンテンツネゴシエーション
Spring MVC は、リクエストパスを調べて、アプリケーションで定義されたマッピング (たとえば、コントローラーメソッドの @GetMapping
アノテーション) と照合することにより、受信 HTTP リクエストをハンドラーにマッピングできます。
Spring Boot は、デフォルトでサフィックスパターンマッチングを無効にすることを選択します。これは、"GET /projects/spring-boot.json"
のようなリクエストが @GetMapping("/projects/spring-boot")
マッピングにマッチングされないことを意味します。これは、Spring MVC アプリケーションのベストプラクティスと見なされています。この機能は、これまで、適切な "Accept" リクエストヘッダーを送信しなかった HTTP クライアントで主に役立ちました。正しいコンテンツ型をクライアントに送信する必要がありました。今日では、コンテントネゴシエーションの信頼性ははるかに高くなっています。
適切な "Accept" リクエストヘッダーを一貫して送信しない HTTP クライアントを処理する方法は他にもあります。サフィックスマッチングを使用する代わりに、クエリパラメーターを使用して、"GET /projects/spring-boot?format=json"
などのリクエストが @GetMapping("/projects/spring-boot")
にマップされるようにすることができます。
spring.mvc.contentnegotiation.favor-parameter=true
spring:
mvc:
contentnegotiation:
favor-parameter: true
または、別のパラメーター名を使用する場合:
spring.mvc.contentnegotiation.favor-parameter=true
spring.mvc.contentnegotiation.parameter-name=myparam
spring:
mvc:
contentnegotiation:
favor-parameter: true
parameter-name: "myparam"
ほとんどの標準メディア型はすぐにサポートされますが、新しいメディア型を定義することもできます。
spring.mvc.contentnegotiation.media-types.markdown=text/markdown
spring:
mvc:
contentnegotiation:
media-types:
markdown: "text/markdown"
サフィックスパターンマッチングは非推奨であり、将来のリリースでは削除される予定です。警告を理解していても、アプリケーションでサフィックスパターンマッチングを使用する場合は、次の構成が必要です。
spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-suffix-pattern=true
spring:
mvc:
contentnegotiation:
favor-path-extension: true
pathmatch:
use-suffix-pattern: true
または、すべてのサフィックスパターンを開くよりも、登録済みのサフィックスパターンのみをサポートする方が安全です。
spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true
spring:
mvc:
contentnegotiation:
favor-path-extension: true
pathmatch:
use-registered-suffix-pattern: true
Spring Framework 5.3 の時点で、Spring MVC は、リクエストパスをコントローラーハンドラーに一致させるためのいくつかの実装戦略をサポートしています。以前は AntPathMatcher
戦略のみをサポートしていましたが、現在は PathPatternParser
も提供しています。Spring Boot は、新しい戦略を選択して選択するための構成プロパティを提供するようになりました。
spring.mvc.pathmatch.matching-strategy=path-pattern-parser
spring:
mvc:
pathmatch:
matching-strategy: "path-pattern-parser"
この新しい実装を検討する必要がある理由の詳細については、専用のブログ投稿 (英語) を参照してください。
PathPatternParser は最適化された実装ですが、一部のパスパターンバリアントの使用を制限し、サフィックスパターンマッチング(spring.mvc.pathmatch.use-suffix-pattern 、spring.mvc.pathmatch.use-registered-suffix-pattern )またはサーブレットプレフィックスを使用した DispatcherServlet のマッピング(spring.mvc.servlet.path )と互換性がありません。 |
1.1.8. ConfigurableWebBindingInitializer
Spring MVC は WebBindingInitializer
を使用して、特定のリクエストに対して WebDataBinder
を初期化します。独自の ConfigurableWebBindingInitializer
@Bean
を作成すると、Spring Boot はそれを使用するように Spring MVC を自動的に構成します。
1.1.9. テンプレートエンジン
REST Web サービスだけでなく、Spring MVC を使用して動的 HTML コンテンツを提供することもできます。Spring MVC は、Thymeleaf、FreeMarker、JSP など、さまざまなテンプレートテクノロジをサポートしています。また、他の多くのテンプレートエンジンには、独自の Spring MVC 統合が含まれています。
Spring Boot には、次のテンプレートエンジンの自動構成サポートが含まれています。
可能であれば、JSP を避ける必要があります。組み込みサーブレットコンテナーで使用する場合、いくつかの既知の制限があります。 |
これらのテンプレートエンジンのいずれかを既定の構成で使用すると、src/main/resources/templates
からテンプレートが自動的に選択されます。
1.1.10. エラー処理
デフォルトでは、Spring Boot はすべてのエラーを適切な方法で処理する /error
マッピングを提供し、サーブレットコンテナーに「グローバル」エラーページとして登録されます。マシンクライアントの場合、エラー、HTTP ステータス、例外メッセージの詳細を含む JSON レスポンスを生成します。ブラウザークライアントの場合、同じデータを HTML 形式でレンダリングする「ホワイトラベル」エラービューがあります(カスタマイズするには、error
に解決される View
を追加します)。
デフォルトのエラー処理動作をカスタマイズする場合に設定できる server.error
プロパティがいくつかあります。付録の “サーバープロパティ” セクションを参照してください。
デフォルトの動作を完全に置き換えるには、ErrorController
を実装してその型の Bean 定義を登録するか、型 ErrorAttributes
の Bean を追加して既存のメカニズムを使用しますが、内容を置き換えます。
BasicErrorController は、カスタム ErrorController の基本クラスとして使用できます。これは、新しいコンテンツ型のハンドラーを追加する場合に特に便利です(デフォルトでは、text/html を具体的に処理し、他のすべてにフォールバックを提供します)。これを行うには、BasicErrorController を継承し、produces 属性を持つ @RequestMapping を使用して public メソッドを追加し、新しい型の Bean を作成します。 |
次の例に示すように、@ControllerAdvice
アノテーションが付けられたクラスを定義して、特定のコントローラーまたは例外型、あるいはその両方を返すように JSON ドキュメントをカスタマイズすることもできます。
@ControllerAdvice(basePackageClasses = SomeController.class)
public class MyControllerAdvice extends ResponseEntityExceptionHandler {
@ResponseBody
@ExceptionHandler(MyException.class)
public ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity<>(new MyErrorBody(status.value(), ex.getMessage()), status);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer code = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
HttpStatus status = HttpStatus.resolve(code);
return (status != null) ? status : HttpStatus.INTERNAL_SERVER_ERROR;
}
}
上記の例では、YourException
が SomeController
と同じパッケージで定義されたコントローラーによってスローされた場合、ErrorAttributes
表現の代わりに CustomErrorType
POJO の JSON 表現が使用されます。
場合によっては、コントローラーレベルで処理されたエラーは、メトリクスインフラストラクチャによって記録されません。アプリケーションは、処理された例外をリクエスト属性として設定することにより、そのような例外がリクエストメトリクスとともに記録されることを保証できます。
@Controller
public class MyController {
@ExceptionHandler(CustomException.class)
String handleCustomException(HttpServletRequest request, CustomException ex) {
request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex);
return "errorView";
}
}
カスタムエラーページ
特定のステータスコードのカスタム HTML エラーページを表示する場合は、/error
ディレクトリにファイルを追加できます。エラーページは、静的 HTML(つまり、任意の静的リソースディレクトリに追加される)にすることも、テンプレートを使用して作成することもできます。ファイルの名前は、正確なステータスコードまたはシリーズマスクである必要があります。
例: 404
を静的 HTML ファイルにマップするには、ディレクトリ構造は次のようになります。
src/ +- main/ +- java/ | + <source code> +- resources/ +- public/ +- error/ | +- 404.html +- <other public assets>
FreeMarker テンプレートを使用してすべての 5xx
エラーをマップするには、ディレクトリ構造は次のようになります。
src/ +- main/ +- java/ | + <source code> +- resources/ +- templates/ +- error/ | +- 5xx.ftlh +- <other templates>
より複雑なマッピングの場合、次の例に示すように、ErrorViewResolver
インターフェースを実装する Bean を追加することもできます。
public class MyErrorViewResolver implements ErrorViewResolver {
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
// Use the request or status to optionally return a ModelAndView
if (status == HttpStatus.INSUFFICIENT_STORAGE) {
// We could add custom model values here
new ModelAndView("myview");
}
return null;
}
}
@ExceptionHandler
メソッドや @ControllerAdvice
などの通常の Spring MVC 機能も使用できます。その後、ErrorController
は未処理の例外を取得します。
Spring MVC 外のエラーページのマッピング
Spring MVC を使用しないアプリケーションの場合、ErrorPageRegistrar
インターフェースを使用して ErrorPages
を直接登録できます。この抽象化は、基盤となる埋め込みサーブレットコンテナーと直接連携し、Spring MVC DispatcherServlet
がなくても機能します。
@Configuration(proxyBeanMethods = false)
public class MyErrorPagesConfiguration {
@Bean
public ErrorPageRegistrar errorPageRegistrar() {
return this::registerErrorPages;
}
private void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
}
}
Filter によって処理されるパスで ErrorPage を登録する場合(Jersey や Wicket などの一部の非 SpringWeb フレームワークで一般的)、次に示すように、Filter を ERROR ディスパッチャーとして明示的に登録する必要があります。次の例: |
@Configuration(proxyBeanMethods = false)
public class MyFilterConfiguration {
@Bean
public FilterRegistrationBean<MyFilter> myFilter() {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(new MyFilter());
// ...
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
return registration;
}
}
デフォルトの FilterRegistrationBean
には ERROR
ディスパッチャー型が含まれていないことに注意してください。
war デプロイでのエラー処理
サーブレットコンテナーにデプロイされると、Spring Boot はエラーページフィルターを使用して、エラーステータスのあるリクエストを適切なエラーページに転送します。サーブレット仕様ではエラーページを登録するための API が提供されていないため、これが必要です。war ファイルをデプロイするコンテナーとアプリケーションが使用するテクノロジーによっては、追加の構成が必要になる場合があります。
エラーページフィルターは、レスポンスがまだコミットされていない場合にのみ、リクエストを正しいエラーページに転送できます。デフォルトでは、WebSphere アプリケーションサーバー 8.0 以降は、サーブレットのサービスメソッドが正常に完了すると、レスポンスをコミットします。com.ibm.ws.webcontainer.invokeFlushAfterService
を false
に設定して、この動作を無効にする必要があります。
Spring Security を使用していて、エラーページのプリンシパルにアクセスする場合は、Spring Security のフィルターがエラーディスパッチで呼び出されるように構成する必要があります。そのためには、spring.security.filter.dispatcher-types
プロパティを async, error, forward, request
に設定します。
1.1.11. CORS サポート
クロスオリジンリソース共有 [Mozilla] (CORS)は、ほとんどのブラウザー (英語) で実装されている W3C 仕様 (英語) であり、IFRAME や JSONP などの安全性の低いアプローチを使用する代わりに、どのようなクロスドメインリクエストを認可するかを柔軟に指定できます。
バージョン 4.2 以降、Spring MVC は CORS をサポートします。Spring Boot アプリケーションで @CrossOrigin
(Javadoc) アノテーションを使用してコントローラーメソッド CORS 構成を使用する場合、特定の構成は必要ありません。グローバル CORS 設定は、次の例に示すように、カスタマイズされた addCorsMappings(CorsRegistry)
メソッドで WebMvcConfigurer
Bean を登録することで定義できます。
@Configuration(proxyBeanMethods = false)
public class MyCorsConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}
1.2. JAX-RS および Jersey
REST エンドポイントに JAX-RS プログラミングモデルを使用する場合は、Spring MVC の代わりに使用可能な実装の 1 つを使用できます。Jersey (英語) と Apache CXF (英語) は、すぐに使用できます。CXF では、アプリケーションコンテキストで Servlet
または Filter
を @Bean
として登録する必要があります。Jersey にはネイティブ Spring サポートがいくつかあるため、スターターとともに Spring Boot での自動構成サポートも提供します。
Jersey を開始するには、spring-boot-starter-jersey
を依存関係として含めてから、次の例に示すように、すべてのエンドポイントを登録する型 ResourceConfig
の @Bean
が 1 つ必要です。
@Component
public class MyJerseyConfig extends ResourceConfig {
public MyJerseyConfig() {
register(MyEndpoint.class);
}
}
Jersey の実行可能アーカイブのスキャンのサポートはかなり制限されています。例: 実行可能な war ファイルを実行している場合、完全に実行可能な jar ファイルまたは WEB-INF/classes で見つかったパッケージ内のエンドポイントをスキャンできません。この制限を回避するには、packages メソッドを使用せず、前の例に示すように、register メソッドを使用してエンドポイントを個別に登録する必要があります。 |
より高度なカスタマイズのために、ResourceConfigCustomizer
を実装する Bean を任意の数だけ登録することもできます。
登録されたすべてのエンドポイントは、次の例に示すように、HTTP リソースアノテーション(@GET
など)を含む @Components
である必要があります。
@Component
@Path("/hello")
public class MyEndpoint {
@GET
public String message() {
return "Hello";
}
}
Endpoint
は Spring @Component
であるため、そのライフサイクルは Spring によって管理され、@Autowired
アノテーションを使用して依存関係を注入し、@Value
アノテーションを使用して外部構成を注入できます。デフォルトでは、Jersey サーブレットが登録され、/*
にマップされます。@ApplicationPath
を ResourceConfig
に追加することにより、マッピングを変更できます。
デフォルトでは、Jersey は、jerseyServletRegistration
という名前の ServletRegistrationBean
型の @Bean
のサーブレットとして設定されます。デフォルトでは、サーブレットは遅延初期化されますが、spring.jersey.servlet.load-on-startup
を設定することでその動作をカスタマイズできます。同じ名前で独自の Bean を作成することにより、その Bean を無効化またはオーバーライドできます。spring.jersey.type=filter
を設定することにより、サーブレットの代わりにフィルターを使用することもできます(この場合、置換またはオーバーライドする @Bean
は jerseyFilterRegistration
です)。フィルターには @Order
があり、spring.jersey.filter.order
で設定できます。Jersey をフィルターとして使用する場合、Jersey によってインターセプトされないリクエストを処理するサーブレットが存在する必要があります。アプリケーションにそのようなサーブレットが含まれていない場合は、server.servlet.register-default-servlet
を true
に設定して、デフォルトのサーブレットを有効にすることをお勧めします。spring.jersey.init.*
を使用してプロパティのマップを指定することにより、サーブレットとフィルターの両方の登録に init パラメーターを指定できます。
1.3. 組み込みサーブレットコンテナーのサポート
サーブレットアプリケーションの場合、Spring Boot には、組み込み Tomcat [Apache] (英語) 、Jetty (英語) 、Undertow [GitHub] (英語) サーバーのサポートが含まれています。ほとんどの開発者は、適切な「スターター」を使用して、完全に構成されたインスタンスを取得します。デフォルトでは、組み込みサーバーはポート 8080
で HTTP リクエストをリッスンします。
1.3.1. サーブレット、フィルター、リスナー
組み込みサーブレットコンテナーを使用する場合、Spring Bean を使用するか、サーブレットコンポーネントをスキャンすることにより、サーブレット、フィルター、すべてのリスナー(HttpSessionListener
など)をサーブレット仕様から登録できます。
サーブレット、フィルター、リスナーを Spring Bean として登録する
Spring Bean である Servlet
、Filter
、サーブレット *Listener
インスタンスはすべて、組み込みコンテナーに登録されます。これは、構成中に application.properties
から値を参照する場合に特に便利です。
デフォルトでは、コンテキストに含まれるサーブレットが 1 つのみの場合、/
にマッピングされます。複数のサーブレット Bean の場合、Bean 名がパスプレフィックスとして使用されます。フィルターは /*
にマップします。
規則ベースのマッピングに十分な柔軟性がない場合は、ServletRegistrationBean
、FilterRegistrationBean
、ServletListenerRegistrationBean
クラスを使用して完全に制御できます。
通常、フィルター Bean は順序付けされていないままにしておくのが安全です。特定の順序が必要な場合は、Filter
に @Order
のアノテーションを付けるか、Ordered
を実装するようにする必要があります。Bean メソッドに @Order
アノテーションを付けて、Filter
の順序を構成することはできません。Filter
クラスを変更して @Order
を追加したり、Ordered
を実装したりできない場合は、Filter
の FilterRegistrationBean
を定義し、setOrder(int)
メソッドを使用して登録 Bean の順序を設定する必要があります。Ordered.HIGHEST_PRECEDENCE
でリクエスト本文を読み取るフィルターを構成することは避けてください。これは、アプリケーションの文字エンコード構成に反する可能性があるためです。サーブレットフィルターがリクエストをラップする場合は、OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER
以下の順序で設定する必要があります。
アプリケーション内のすべての Filter の順序を確認するには、web ロギンググループ(logging.level.web=debug )のデバッグレベルロギングを有効にします。登録されたフィルターの詳細(順序や URL パターンなど)は、起動時にログに記録されます。 |
Filter Bean はアプリケーションのライフサイクルの非常に早い段階で初期化されるため、登録するときは注意してください。他の Bean と相互作用する Filter を登録する必要がある場合は、代わりに DelegatingFilterProxyRegistrationBean (Javadoc) の使用を検討してください。 |
1.3.2. サーブレットコンテキストの初期化
組み込みサーブレットコンテナーは、サーブレット 3.0 + javax.servlet.ServletContainerInitializer
インターフェースまたは Spring の org.springframework.web.WebApplicationInitializer
インターフェースを直接実行しません。これは、war 内で実行するように設計されたサードパーティライブラリが Spring Boot アプリケーションを破壊するリスクを軽減することを目的とした意図的な設計上の決定です。
Spring Boot アプリケーションでサーブレットコンテキストの初期化を実行する必要がある場合は、org.springframework.boot.web.servlet.ServletContextInitializer
インターフェースを実装する Bean を登録する必要があります。単一の onStartup
メソッドは ServletContext
へのアクセスを提供し、必要に応じて、既存の WebApplicationInitializer
へのアダプターとして簡単に使用できます。
1.3.3. ServletWebServerApplicationContext
内部的には、Spring Boot は組み込みサーブレットコンテナーのサポートに異なる型の ApplicationContext
を使用します。ServletWebServerApplicationContext
は、単一の ServletWebServerFactory
Bean を検索することによってそれ自体をブートストラップする特殊な型の WebApplicationContext
です。通常、TomcatServletWebServerFactory
、JettyServletWebServerFactory
、UndertowServletWebServerFactory
は自動構成されています。
通常、これらの実装クラスを意識する必要はありません。ほとんどのアプリケーションは自動構成され、適切な ApplicationContext および ServletWebServerFactory がユーザーに代わって作成されます。 |
1.3.4. 埋め込みサーブレットコンテナーのカスタマイズ
一般的なサーブレットコンテナー設定は、Spring Environment
プロパティを使用して構成できます。通常、application.properties
または application.yaml
ファイルでプロパティを定義します。
一般的なサーバー設定は次のとおりです。
ネットワーク設定: 受信 HTTP リクエストのリスンポート(
server.port
)、server.address
にバインドするインターフェースアドレスなど。セッション設定: セッションが永続的か(
server.servlet.session.persistent
)、セッションタイムアウト(server.servlet.session.timeout
)、セッションデータの場所(server.servlet.session.store-dir
)、セッション Cookie 構成(server.servlet.session.cookie.*
)。エラー管理: エラーページ(
server.error.path
)などの場所。
Spring Boot は、可能な限り共通の設定を公開しようとしますが、常に可能とは限りません。これらの場合、専用の名前空間はサーバー固有のカスタマイズを提供します(server.tomcat
および server.undertow
を参照)。たとえば、アクセスログは、組み込みサーブレットコンテナーの特定の機能を使用して設定できます。
完全なリストについては、ServerProperties [GitHub] (英語) クラスを参照してください。 |
SameSite クッキー
SameSite
cookie 属性は、クロスサイトリクエストで Cookie を送信するかどうか、および送信する方法を制御するために Web ブラウザーで使用できます。この属性は、属性が欠落しているときに使用されるデフォルト値を変更し始めた最新の Web ブラウザーに特に関係があります。
セッション Cookie の SameSite
属性を変更する場合は、server.servlet.session.cookie.same-site
プロパティを使用できます。このプロパティは、自動構成された Tomcat、Jetty、Undertow サーバーでサポートされています。また、Spring Session サーブレットベースの SessionRepository
Bean を構成するためにも使用されます。
例: セッション Cookie に None
の SameSite
属性を持たせたい場合は、application.properties
または application.yaml
ファイルに以下を追加できます。
server.servlet.session.cookie.same-site=none
server:
servlet:
session:
cookie:
same-site: "none"
HttpServletResponse
に追加された他の Cookie の SameSite
属性を変更する場合は、CookieSameSiteSupplier
を使用できます。CookieSameSiteSupplier
には Cookie
が渡され、SameSite
値または null
を返す場合があります。
特定の Cookie をすばやく照合するために使用できる便利なファクトリおよびフィルターメソッドがいくつかあります。例: 次の Bean を追加すると、正規表現 myapp.*
と一致する名前のすべての Cookie に Lax
の SameSite
が自動的に適用されます。
@Configuration(proxyBeanMethods = false)
public class MySameSiteConfiguration {
@Bean
public CookieSameSiteSupplier applicationCookieSameSiteSupplier() {
return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*");
}
}
プログラムによるカスタマイズ
組み込みサーブレットコンテナーをプログラムで設定する必要がある場合は、WebServerFactoryCustomizer
インターフェースを実装する Spring Bean を登録できます。WebServerFactoryCustomizer
は、多数のカスタマイズ setter メソッドを含む ConfigurableServletWebServerFactory
へのアクセスを提供します。次の例は、プログラムでポートを設定する方法を示しています。
@Component
public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory server) {
server.setPort(9000);
}
}
TomcatServletWebServerFactory
、JettyServletWebServerFactory
、UndertowServletWebServerFactory
は ConfigurableServletWebServerFactory
の専用バリアントであり、Tomcat、Jetty、Undertow 用にそれぞれ追加のカスタマイズ setter メソッドがあります。次の例は、Tomcat 固有の構成オプションへのアクセスを提供する TomcatServletWebServerFactory
をカスタマイズする方法を示しています。
@Component
public class MyTomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory server) {
server.addConnectorCustomizers((connector) -> connector.setAsyncTimeout(Duration.ofSeconds(20).toMillis()));
}
}
ConfigurableServletWebServerFactory を直接カスタマイズする
ServletWebServerFactory
から拡張する必要があるより高度なユースケースの場合は、そのような型の Bean を自分で公開できます。
Setter は、多くの構成オプション用に提供されています。よりエキゾチックな何かをする必要がある場合、いくつかの protected メソッド「フック」も提供されます。詳細については、ソースコードのドキュメント (Javadoc) を参照してください。
自動構成されたカスタマイザーは引き続きカスタムファクトリに適用されるため、そのオプションは慎重に使用してください。 |
1.3.5. JSP の制限
組み込みサーブレットコンテナーを使用する(実行可能アーカイブとしてパッケージ化されている)Spring Boot アプリケーションを実行する場合、JSP サポートにはいくつかの制限があります。
Jetty と Tomcat では、war パッケージを使用すれば動作するはずです。実行可能な war は、
java -jar
で起動すると動作し、任意の標準コンテナーに配備することもできます。実行可能 jar を使用する場合、JSP はサポートされません。Undertow は JSP をサポートしていません。
カスタム
error.jsp
ページを作成しても、エラー処理のデフォルトビューは上書きされません。代わりにカスタムエラーページを使用する必要があります。
2. リアクティブ Web アプリケーション
Spring Boot は、Spring Webflux の自動構成を提供することにより、リアクティブ Web アプリケーションの開発を簡素化します。
2.1. 「Spring WebFlux フレームワーク」
Spring WebFlux は、Spring Framework 5.0 で導入された新しいリアクティブ Web フレームワークです。Spring MVC とは異なり、サーブレット API を必要とせず、完全に非同期でノンブロッキングであり、Reactor プロジェクト (英語) を通じて Reactive Streams (英語) 仕様を実装します。
Spring WebFlux には、関数型とアノテーション型の 2 つのフレーバーがあります。次の例に示すように、アノテーションベースのものは Spring MVC モデルに非常に近いものです。
@RestController
@RequestMapping("/users")
public class MyRestController {
private final UserRepository userRepository;
private final CustomerRepository customerRepository;
public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {
this.userRepository = userRepository;
this.customerRepository = customerRepository;
}
@GetMapping("/{user}")
public Mono<User> getUser(@PathVariable Long userId) {
return this.userRepository.findById(userId);
}
@GetMapping("/{user}/customers")
public Flux<Customer> getUserCustomers(@PathVariable Long userId) {
return this.userRepository.findById(userId).flatMapMany(this.customerRepository::findByUser);
}
@DeleteMapping("/{user}")
public void deleteUser(@PathVariable Long userId) {
this.userRepository.deleteById(userId);
}
}
次の例に示すように、関数型バリアントである "WebFlux.fn" は、ルーティング構成をリクエストの実際の処理から分離します。
@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {
private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);
@Bean
public RouterFunction<ServerResponse> monoRouterFunction(MyUserHandler userHandler) {
return route(
GET("/{user}").and(ACCEPT_JSON), userHandler::getUser).andRoute(
GET("/{user}/customers").and(ACCEPT_JSON), userHandler::getUserCustomers).andRoute(
DELETE("/{user}").and(ACCEPT_JSON), userHandler::deleteUser);
}
}
@Component
public class MyUserHandler {
public Mono<ServerResponse> getUser(ServerRequest request) {
...
}
public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
...
}
public Mono<ServerResponse> deleteUser(ServerRequest request) {
...
}
}
WebFlux は Spring Framework の一部であり、詳細な情報はリファレンスドキュメントで入手できます。
RouterFunction Bean をいくつでも定義して、ルーターの定義をモジュール化できます。優先順位を適用する必要がある場合は、Bean をオーダーできます。 |
開始するには、spring-boot-starter-webflux
モジュールをアプリケーションに追加します。
アプリケーションに spring-boot-starter-web モジュールと spring-boot-starter-webflux モジュールの両方を追加すると、WebFlux ではなく Spring Boot が Spring MVC を自動構成します。この動作が選択されたのは、多くの Spring 開発者が spring-boot-starter-webflux を Spring MVC アプリケーションに追加してリアクティブ WebClient を使用するためです。選択したアプリケーションの種類を SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE) に設定することで、引き続き選択を強制できます。 |
次の例に示すように、関数型バリアントである "WebFlux.fn" は、ルーティング構成をリクエストの実際の処理から分離します。
@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {
private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);
@Bean
public RouterFunction<ServerResponse> monoRouterFunction(MyUserHandler userHandler) {
return route(
GET("/{user}").and(ACCEPT_JSON), userHandler::getUser).andRoute(
GET("/{user}/customers").and(ACCEPT_JSON), userHandler::getUserCustomers).andRoute(
DELETE("/{user}").and(ACCEPT_JSON), userHandler::deleteUser);
}
}
@Component
public class MyUserHandler {
public Mono<ServerResponse> getUser(ServerRequest request) {
...
}
public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
...
}
public Mono<ServerResponse> deleteUser(ServerRequest request) {
...
}
}
WebFlux は Spring Framework の一部であり、詳細な情報はリファレンスドキュメントで入手できます。
RouterFunction Bean をいくつでも定義して、ルーターの定義をモジュール化できます。優先順位を適用する必要がある場合は、Bean をオーダーできます。 |
開始するには、spring-boot-starter-webflux
モジュールをアプリケーションに追加します。
アプリケーションに spring-boot-starter-web モジュールと spring-boot-starter-webflux モジュールの両方を追加すると、WebFlux ではなく Spring Boot が Spring MVC を自動構成します。この動作が選択されたのは、多くの Spring 開発者が spring-boot-starter-webflux を Spring MVC アプリケーションに追加してリアクティブ WebClient を使用するためです。選択したアプリケーションの種類を SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE) に設定することで、引き続き選択を強制できます。 |
2.1.1. Spring WebFlux 自動構成
Spring Boot は、ほとんどのアプリケーションで適切に機能する Spring WebFlux の自動構成を提供します。
自動構成により、Spring のデフォルトに加えて次の機能が追加されます。
Spring Boot WebFlux 機能を保持し、さらに WebFlux の構成を追加する場合、@EnableWebFlux
なしで型 WebFluxConfigurer
の独自の @Configuration
クラスを追加できます。
Spring WebFlux を完全に制御したい場合は、@EnableWebFlux
アノテーションが付けられた独自の @Configuration
を追加できます。
2.1.2. HttpMessageReaders および HttpMessageWriters を使用した HTTP コーデック
Spring WebFlux は、HttpMessageReader
および HttpMessageWriter
インターフェースを使用して、HTTP リクエストおよびレスポンスを変換します。これらは、クラスパスで使用可能なライブラリを調べることにより、実用的なデフォルトを持つように CodecConfigurer
で構成されます。
Spring Boot は、コーデックの専用構成プロパティ spring.codec.*
を提供します。また、CodecCustomizer
インスタンスを使用して、さらにカスタマイズを適用します。例: spring.jackson.*
設定キーは Jackson コーデックに適用されます。
コーデックを追加またはカスタマイズする必要がある場合は、次の例に示すように、カスタム CodecCustomizer
コンポーネントを作成できます。
@Configuration(proxyBeanMethods = false)
public class MyCodecsConfiguration {
@Bean
public CodecCustomizer myCodecCustomizer() {
return (configurer) -> {
configurer.registerDefaults(false);
configurer.customCodecs().register(new ServerSentEventHttpMessageReader());
// ...
};
}
}
Boot のカスタム JSON シリアライザーとデシリアライザーを活用することもできます。
2.1.3. 静的コンテンツ
デフォルトでは、Spring Boot は、クラスパス内の /static
(または /public
または /resources
または /META-INF/resources
)と呼ばれるディレクトリから静的コンテンツを提供します。Spring WebFlux の ResourceWebHandler
を使用するため、独自の WebFluxConfigurer
を追加して addResourceHandlers
メソッドをオーバーライドすることにより、その動作を変更できます。
デフォルトでは、リソースは /**
にマップされますが、spring.webflux.static-path-pattern
プロパティを設定することでそれを調整できます。たとえば、すべてのリソースを /resources/**
に再配置するには、次のようにします。
spring.webflux.static-path-pattern=/resources/**
spring:
webflux:
static-path-pattern: "/resources/**"
spring.web.resources.static-locations
を使用して、静的リソースの場所をカスタマイズすることもできます。これにより、デフォルト値がディレクトリの場所のリストに置き換えられます。そうすると、デフォルトのウェルカムページ検出がカスタムの場所に切り替わります。起動時にいずれかの場所に index.html
がある場合、アプリケーションのホームページです。
前述の「標準」の静的リソースの場所に加えて、Webjars コンテンツ (英語) には特別なケースが作成されます。WebZZ 形式でパッケージ化されている場合、/webjars/**
にパスを持つリソースは jar ファイルから提供されます。
Spring WebFlux アプリケーションはサーブレット API に厳密に依存していないため、war ファイルとしてデプロイすることはできず、src/main/webapp ディレクトリを使用しません。 |
2.1.4. ウェルカムページ
Spring Boot は、静的なウェルカムページとテンプレート化されたウェルカムページの両方をサポートしています。最初に、構成された静的コンテンツの場所で index.html
ファイルを探します。見つからない場合は、index
テンプレートを探します。どちらかが見つかった場合、アプリケーションのウェルカムページとして自動的に使用されます。
2.1.5. テンプレートエンジン
REST Web サービスだけでなく、Spring WebFlux を使用して動的 HTML コンテンツを提供することもできます。Spring WebFlux は、Thymeleaf、FreeMarker、Mustache など、さまざまなテンプレートテクノロジーをサポートしています。
Spring Boot には、次のテンプレートエンジンの自動構成サポートが含まれています。
これらのテンプレートエンジンのいずれかを既定の構成で使用すると、src/main/resources/templates
からテンプレートが自動的に選択されます。
2.1.6. エラー処理
Spring Boot は、すべてのエラーを適切な方法で処理する WebExceptionHandler
を提供します。処理順序でのその位置は、WebFlux によって提供されるハンドラーの直前であり、最後に考慮されます。マシンクライアントの場合、エラー、HTTP ステータス、例外メッセージの詳細を含む JSON レスポンスを生成します。ブラウザークライアントには、同じデータを HTML 形式でレンダリングする「ホワイトラベル」エラーハンドラーがあります。また、独自の HTML テンプレートを提供してエラーを表示することもできます(次のセクションを参照)。
この機能をカスタマイズするための最初のステップは、多くの場合、既存のメカニズムを使用しますが、エラーの内容を置換または拡張することを伴います。そのために、型 ErrorAttributes
の Bean を追加できます。
エラー処理の動作を変更するには、ErrorWebExceptionHandler
を実装し、その型の Bean 定義を登録できます。ErrorWebExceptionHandler
は非常に低レベルであるため、Spring Boot は次の例に示すように、WebFlux の関数方法でエラーを処理できる便利な AbstractErrorWebExceptionHandler
も提供します。
@Component
public class MyErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, Resources resources,
ApplicationContext applicationContext) {
super(errorAttributes, resources, applicationContext);
}
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(this::acceptsXml, this::handleErrorAsXml);
}
private boolean acceptsXml(ServerRequest request) {
return request.headers().accept().contains(MediaType.APPLICATION_XML);
}
public Mono<ServerResponse> handleErrorAsXml(ServerRequest request) {
BodyBuilder builder = ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR);
// ... additional builder calls
return builder.build();
}
}
より完全な図を得るには、DefaultErrorWebExceptionHandler
を直接サブクラス化し、特定のメソッドをオーバーライドすることもできます。
場合によっては、コントローラーまたはハンドラー関数レベルで処理されたエラーは、メトリクスインフラストラクチャによって記録されません。アプリケーションは、処理された例外をリクエスト属性として設定することにより、そのような例外がリクエストメトリクスとともに記録されることを保証できます。
@Controller
public class MyExceptionHandlingController {
@GetMapping("/profile")
public Rendering userProfile() {
// ...
throw new IllegalStateException();
}
@ExceptionHandler(IllegalStateException.class)
public Rendering handleIllegalState(ServerWebExchange exchange, IllegalStateException exc) {
exchange.getAttributes().putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, exc);
return Rendering.view("errorView").modelAttribute("message", exc.getMessage()).build();
}
}
カスタムエラーページ
特定のステータスコードのカスタム HTML エラーページを表示する場合は、/error
ディレクトリにファイルを追加できます。エラーページは、静的 HTML(つまり、任意の静的リソースディレクトリに追加される)にすることも、テンプレートで作成することもできます。ファイルの名前は、正確なステータスコードまたはシリーズマスクである必要があります。
例: 404
を静的 HTML ファイルにマップするには、ディレクトリ構造は次のようになります。
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
Mustache テンプレートを使用してすべての 5xx
エラーをマップするには、ディレクトリ構造は次のようになります。
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.mustache
+- <other templates>
2.1.7. Web フィルター
Spring WebFlux は、HTTP リクエスト / レスポンス交換をフィルタリングするために実装できる WebFilter
インターフェースを提供します。アプリケーションコンテキストで見つかった WebFilter
Bean は、各交換のフィルタリングに自動的に使用されます。
フィルターの順序が重要な場合、Ordered
を実装するか、@Order
でアノテーションを付けることができます。Spring Boot の自動構成により、Web フィルターが構成される場合があります。その場合、次の表に示す順序が使用されます。
Web フィルター | 順序 |
---|---|
|
|
|
|
|
|
2.2. 埋め込み型リアクティブサーバーのサポート
Spring Boot には、Reactor Netty、Tomcat、Jetty、Undertow の組み込みリアクティブ Web サーバーのサポートが含まれています。ほとんどの開発者は、適切な「スターター」を使用して、完全に構成されたインスタンスを取得します。デフォルトでは、組み込みサーバーはポート 8080 で HTTP リクエストをリッスンします。
2.3. リアクティブサーバーリソースの構成
Reactor Netty または Jetty サーバーを自動構成する場合、Spring Boot は、サーバーインスタンスに HTTP リソースを提供する特定の Bean ReactorResourceFactory
または JettyResourceFactory
を作成します。
デフォルトでは、これらのリソースは、最適なパフォーマンスのために、Reactor Netty および Jetty クライアントとも共有されます。
同じテクノロジーがサーバーとクライアントに使用されます
クライアントインスタンスは、Spring Boot によって自動構成された
WebClient.Builder
Bean を使用して構築されます
開発者は、カスタム ReactorResourceFactory
または JettyResourceFactory
Bean を提供することにより、Jetty および Reactor Netty のリソース構成をオーバーライドできます。これは、クライアントとサーバーの両方に適用されます。
WebClient ランタイムセクションでクライアント側のリソース構成について詳しく知ることができます。
3. グレースフルシャットダウン
グレースフルシャットダウンは、4 つの組み込み Web サーバー(Jetty、Reactor Netty、Tomcat、Undertow)のすべてと、リアクティブ Web アプリケーションとサーブレットベースの Web アプリケーションの両方でサポートされています。これは、アプリケーションコンテキストを閉じる一部として発生し、SmartLifecycle
Bean を停止する最初のフェーズで実行されます。この停止処理は、既存のリクエストの補完は許可されるが、新しいリクエストは許可されない猶予期間を提供するタイムアウトを使用します。新しいリクエストが許可されない正確な方法は、使用されている Web サーバーによって異なります。Jetty、Reactor Netty、および Tomcat は、ネットワーク層でのリクエストの受け入れを停止します。Undertow はリクエストを受け入れますが、サービスを利用できない (503) レスポンスですぐにレスポンスします。
Tomcat による正常なシャットダウンには、Tomcat 9.0.33 以降が必要です。 |
グレースフルシャットダウンを有効にするには、次の例に示すように、server.shutdown
プロパティを構成します。
server.shutdown=graceful
server:
shutdown: "graceful"
タイムアウト期間を構成するには、次の例に示すように、spring.lifecycle.timeout-per-shutdown-phase
プロパティを構成します。
spring.lifecycle.timeout-per-shutdown-phase=20s
spring:
lifecycle:
timeout-per-shutdown-phase: "20s"
IDE が適切な SIGTERM 信号を送信しない場合、IDE でグレースフルシャットダウンを使用すると正しく機能しない可能性があります。詳細については、IDE のドキュメントを参照してください。 |
4. Spring Security
Spring Security がクラスパスにある場合、Web アプリケーションはデフォルトで保護されます。Spring Boot は、Spring Security のコンテンツネゴシエーション戦略に基づいて、httpBasic
と formLogin
のどちらを使用するかを決定します。メソッドレベルのセキュリティを Web アプリケーションに追加するために、必要な設定で @EnableGlobalMethodSecurity
を追加することもできます。追加情報は Spring Security リファレンスガイドにあります。
デフォルトの UserDetailsService
には単一のユーザーがいます。ユーザー名は user
であり、パスワードはランダムであり、次の例に示すように、アプリケーションの起動時に INFO レベルで出力されます。
Using generated security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35
ロギング構成を微調整する場合は、org.springframework.boot.autoconfigure.security カテゴリが INFO -level メッセージを記録するように設定されていることを確認してください。それ以外の場合、デフォルトのパスワードは出力されません。 |
spring.security.user.name
および spring.security.user.password
を提供することにより、ユーザー名とパスワードを変更できます。
Web アプリケーションでデフォルトで取得する基本機能は次のとおりです。
UserDetailsService
(または WebFlux アプリケーションの場合はReactiveUserDetailsService
)メモリ内ストアを持つ Bean と、生成されたパスワードを持つ単一のユーザー(ユーザーのプロパティについてはSecurityProperties.User
(Javadoc) を参照)。アプリケーション全体(アクチュエーターがクラスパス上にある場合はアクチュエーターエンドポイントを含む)に対するフォームベースのログインまたは HTTP Basic セキュリティ(リクエストの
Accept
ヘッダーに依存)。認証イベントを公開するための
DefaultAuthenticationEventPublisher
。
Bean を追加することにより、異なる AuthenticationEventPublisher
を提供できます。
4.1. MVC セキュリティ
デフォルトのセキュリティ構成は、SecurityAutoConfiguration
および UserDetailsServiceAutoConfiguration
に実装されています。SecurityAutoConfiguration
は Web セキュリティのために SpringBootWebSecurityConfiguration
をインポートし、UserDetailsServiceAutoConfiguration
は認証を構成します。これは Web 以外のアプリケーションにも関連します。デフォルトの Web アプリケーションセキュリティ構成を完全にオフにするか、OAuth2 クライアントやリソースサーバーなどの複数の Spring Security コンポーネントを組み合わせるには、型 SecurityFilterChain
の Bean を追加します(そうしても、UserDetailsService
構成またはアクチュエーターのセキュリティは無効になりません)。
UserDetailsService
構成をオフにするために、型 UserDetailsService
、AuthenticationProvider
、AuthenticationManager
の Bean を追加することもできます。
カスタム SecurityFilterChain
または WebSecurityConfigurerAdapter
Bean を追加することにより、アクセスルールをオーバーライドできます。Spring Boot は、アクチュエーターエンドポイントと静的リソースのアクセスルールを上書きするために使用できる便利なメソッドを提供します。EndpointRequest
を使用して、management.endpoints.web.base-path
プロパティに基づく RequestMatcher
を作成できます。PathRequest
を使用して、一般的に使用される場所にあるリソースの RequestMatcher
を作成できます。
4.2. WebFlux セキュリティ
Spring MVC アプリケーションと同様に、spring-boot-starter-security
依存関係を追加することで WebFlux アプリケーションを保護できます。デフォルトのセキュリティ設定は ReactiveSecurityAutoConfiguration
および UserDetailsServiceAutoConfiguration
に実装されています。ReactiveSecurityAutoConfiguration
は Web セキュリティのために WebFluxSecurityConfiguration
をインポートし、UserDetailsServiceAutoConfiguration
は認証を構成します。これは、非 Web アプリケーションにも関連します。デフォルトの Web アプリケーションセキュリティ設定を完全にオフにするには、型 WebFilterChainProxy
の Bean を追加します (追加しても UserDetailsService
設定やアクチュエーターのセキュリティは無効になりません)。
UserDetailsService
構成もオフにするには、型 ReactiveUserDetailsService
または ReactiveAuthenticationManager
の Bean を追加できます。
カスタム SecurityWebFilterChain
Bean を追加することにより、アクセスルールと、OAuth 2 クライアントやリソースサーバーなどの複数の Spring Security コンポーネントの使用を構成できます。Spring Boot は、アクチュエーターエンドポイントおよび静的リソースのアクセスルールをオーバーライドするために使用できる便利なメソッドを提供します。EndpointRequest
を使用して、management.endpoints.web.base-path
プロパティに基づく ServerWebExchangeMatcher
を作成できます。
PathRequest
を使用して、一般的に使用される場所のリソース用の ServerWebExchangeMatcher
を作成できます。
例: 次のようなものを追加して、セキュリティ構成をカスタマイズできます。
@Configuration(proxyBeanMethods = false)
public class MyWebFluxSecurityConfiguration {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange((spec) -> {
spec.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
spec.pathMatchers("/foo", "/bar").authenticated();
});
http.formLogin();
return http.build();
}
}
4.3. OAuth2
OAuth2 (英語) は、Spring でサポートされている広く使用されている認可フレームワークです。
4.3.1. クライアント
クラスパスに spring-security-oauth2-client
がある場合、いくつかの自動構成を利用して OAuth2/Open ID Connect クライアントを設定できます。この構成では、OAuth2ClientProperties
のプロパティを使用します。同じプロパティが、サーブレットアプリケーションとリアクティブアプリケーションの両方に適用されます。
次の例に示すように、spring.security.oauth2.client
プレフィックスに複数の OAuth2 クライアントとプロバイダーを登録できます。
spring.security.oauth2.client.registration.my-client-1.client-id=abcd
spring.security.oauth2.client.registration.my-client-1.client-secret=password
spring.security.oauth2.client.registration.my-client-1.client-name=Client for user scope
spring.security.oauth2.client.registration.my-client-1.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-1.scope=user
spring.security.oauth2.client.registration.my-client-1.redirect-uri=https://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-1.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-1.authorization-grant-type=authorization-code
spring.security.oauth2.client.registration.my-client-2.client-id=abcd
spring.security.oauth2.client.registration.my-client-2.client-secret=password
spring.security.oauth2.client.registration.my-client-2.client-name=Client for email scope
spring.security.oauth2.client.registration.my-client-2.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-2.scope=email
spring.security.oauth2.client.registration.my-client-2.redirect-uri=https://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-2.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-2.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri=https://my-auth-server/oauth/authorize
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=https://my-auth-server/oauth/token
spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri=https://my-auth-server/userinfo
spring.security.oauth2.client.provider.my-oauth-provider.user-info-authentication-method=header
spring.security.oauth2.client.provider.my-oauth-provider.jwk-set-uri=https://my-auth-server/token_keys
spring.security.oauth2.client.provider.my-oauth-provider.user-name-attribute=name
spring:
security:
oauth2:
client:
registration:
my-client-1:
client-id: "abcd"
client-secret: "password"
client-name: "Client for user scope"
provider: "my-oauth-provider"
scope: "user"
redirect-uri: "https://my-redirect-uri.com"
client-authentication-method: "basic"
authorization-grant-type: "authorization-code"
my-client-2:
client-id: "abcd"
client-secret: "password"
client-name: "Client for email scope"
provider: "my-oauth-provider"
scope: "email"
redirect-uri: "https://my-redirect-uri.com"
client-authentication-method: "basic"
authorization-grant-type: "authorization_code"
provider:
my-oauth-provider:
authorization-uri: "https://my-auth-server/oauth/authorize"
token-uri: "https://my-auth-server/oauth/token"
user-info-uri: "https://my-auth-server/userinfo"
user-info-authentication-method: "header"
jwk-set-uri: "https://my-auth-server/token_keys"
user-name-attribute: "name"
OpenID Connect ディスカバリ (英語) をサポートする OpenIDConnect プロバイダーの場合、構成をさらに簡素化できます。プロバイダーは、発行者 ID としてアサートする URI である issuer-uri
を使用して構成する必要があります。例: 提供された issuer-uri
が "https://example.com" の場合、OpenID Provider Configuration Request
は "https://example.com/.well-known/openid-configuration" になります。結果は OpenID Provider Configuration Response
になると予想されます。次の例は、OpenID 接続プロバイダーを issuer-uri
で構成する方法を示しています。
spring.security.oauth2.client.provider.oidc-provider.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/
spring:
security:
oauth2:
client:
provider:
oidc-provider:
issuer-uri: "https://dev-123456.oktapreview.com/oauth2/default/"
デフォルトでは、Spring Security の OAuth2LoginAuthenticationFilter
は /login/oauth2/code/*
に一致する URL のみを処理します。redirect-uri
をカスタマイズして別のパターンを使用する場合は、そのカスタムパターンを処理するための構成を提供する必要があります。例: サーブレットアプリケーションの場合、次のような独自の SecurityFilterChain
を追加できます。
@Configuration(proxyBeanMethods = false)
public class MyOAuthClientConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
http.oauth2Login().redirectionEndpoint().baseUri("custom-callback");
return http.build();
}
}
Spring Boot は、クライアント登録の管理のために Spring Security によって使用される InMemoryOAuth2AuthorizedClientService を自動構成します。InMemoryOAuth2AuthorizedClientService の機能には制限があるため、開発環境でのみ使用することをお勧めします。本番環境では、JdbcOAuth2AuthorizedClientService を使用するか、OAuth2AuthorizedClientService の独自の実装を作成することを検討してください。 |
一般的なプロバイダーの OAuth2 クライアント登録
Google、Github、Facebook、Okta などの一般的な OAuth2 プロバイダーと OpenID プロバイダーについては、プロバイダーのデフォルトのセット (それぞれ google
、github
、facebook
、okta
) が提供されています。
これらのプロバイダーをカスタマイズする必要がない場合は、provider
属性をデフォルトを推測する必要がある属性に設定できます。また、クライアント登録のキーがデフォルトでサポートされているプロバイダーと一致する場合、Spring Boot も同様に推測します。
つまり、次の例の 2 つの構成では Google プロバイダーを使用します。
spring.security.oauth2.client.registration.my-client.client-id=abcd
spring.security.oauth2.client.registration.my-client.client-secret=password
spring.security.oauth2.client.registration.my-client.provider=google
spring.security.oauth2.client.registration.google.client-id=abcd
spring.security.oauth2.client.registration.google.client-secret=password
spring:
security:
oauth2:
client:
registration:
my-client:
client-id: "abcd"
client-secret: "password"
provider: "google"
google:
client-id: "abcd"
client-secret: "password"
4.3.2. リソースサーバー
クラスパスに spring-security-oauth2-resource-server
がある場合、Spring Boot は OAuth2 リソースサーバーをセットアップできます。JWT 構成の場合、次の例に示すように、JWK セット URI または OIDC 発行者 URI を指定する必要があります。
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/oauth2/default/v1/keys
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: "https://example.com/oauth2/default/v1/keys"
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: "https://dev-123456.oktapreview.com/oauth2/default/"
認可サーバーが JWK Set URI をサポートしていない場合、JWT の署名の検証に使用される公開鍵でリソースサーバーを構成できます。これは、spring.security.oauth2.resourceserver.jwt.public-key-location プロパティを使用して実行できます。値は、PEM エンコードされた x509 形式の公開キーを含むファイルを指す必要があります。 |
同じプロパティは、サーブレットアプリケーションとリアクティブアプリケーションの両方に適用できます。
または、サーブレットアプリケーション用に独自の JwtDecoder
Bean を定義するか、リアクティブアプリケーション用に ReactiveJwtDecoder
を定義できます。
JWT の代わりに Opaque トークンが使用されている場合は、次のプロパティを構成して、イントロスペクションを通じてトークンを検証できます。
spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://example.com/check-token
spring.security.oauth2.resourceserver.opaquetoken.client-id=my-client-id
spring.security.oauth2.resourceserver.opaquetoken.client-secret=my-client-secret
spring:
security:
oauth2:
resourceserver:
opaquetoken:
introspection-uri: "https://example.com/check-token"
client-id: "my-client-id"
client-secret: "my-client-secret"
繰り返しますが、同じプロパティがサーブレットとリアクティブの両方のアプリケーションに適用可能です。
または、サーブレットアプリケーション用に独自の OpaqueTokenIntrospector
Bean を定義するか、リアクティブアプリケーション用に ReactiveOpaqueTokenIntrospector
を定義できます。
4.3.3. 認可サーバー
現在、Spring Security は OAuth 2.0 認可サーバーの実装をサポートしていません。ただし、この機能は Spring Security OAuth プロジェクトから利用でき、最終的には Spring Security に完全に置き換えられます。それまでは、spring-security-oauth2-autoconfigure
モジュールを使用して、OAuth 2.0 認可サーバーを簡単にセットアップできます。手順については、ドキュメントを参照してください。
4.4. SAML 2.0
4.4.1. 証明書利用者
クラスパスに spring-security-saml2-service-provider
がある場合は、自動構成を利用して SAML 2.0 依存パーティをセットアップできます。この構成では、Saml2RelyingPartyProperties
のプロパティを使用します。
証明書利用者登録は、ID プロバイダー IDP とサービスプロバイダー SP の間のペア構成を表します。次の例に示すように、spring.security.saml2.relyingparty
プレフィックスに複数の証明書利用者を登録できます。
spring.security.saml2.relyingparty.registration.my-relying-party1.signing.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-party1.signing.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-party1.decryption.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-party1.decryption.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-party1.identityprovider.verification.credentials[0].certificate-location=path-to-verification-cert
spring.security.saml2.relyingparty.registration.my-relying-party1.identityprovider.entity-id=remote-idp-entity-id1
spring.security.saml2.relyingparty.registration.my-relying-party1.identityprovider.sso-url=https://remoteidp1.sso.url
spring.security.saml2.relyingparty.registration.my-relying-party2.signing.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-party2.signing.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-party2.decryption.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-party2.decryption.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-party2.identityprovider.verification.credentials[0].certificate-location=path-to-other-verification-cert
spring.security.saml2.relyingparty.registration.my-relying-party2.identityprovider.entity-id=remote-idp-entity-id2
spring.security.saml2.relyingparty.registration.my-relying-party2.identityprovider.sso-url=https://remoteidp2.sso.url
spring:
security:
saml2:
relyingparty:
registration:
my-relying-party1:
signing:
credentials:
- private-key-location: "path-to-private-key"
certificate-location: "path-to-certificate"
decryption:
credentials:
- private-key-location: "path-to-private-key"
certificate-location: "path-to-certificate"
identityprovider:
verification:
credentials:
- certificate-location: "path-to-verification-cert"
entity-id: "remote-idp-entity-id1"
sso-url: "https://remoteidp1.sso.url"
my-relying-party2:
signing:
credentials:
- private-key-location: "path-to-private-key"
certificate-location: "path-to-certificate"
decryption:
credentials:
- private-key-location: "path-to-private-key"
certificate-location: "path-to-certificate"
identityprovider:
verification:
credentials:
- certificate-location: "path-to-other-verification-cert"
entity-id: "remote-idp-entity-id2"
sso-url: "https://remoteidp2.sso.url"
5. Spring Session
Spring Boot は、さまざまなデータストアに Spring Session 自動構成を提供します。サーブレット Web アプリケーションを構築する場合、次のストアを自動構成できます。
JDBC
Redis
Hazelcast
MongoDB
サーブレットの自動構成により、@Enable*HttpSession
を使用する必要がなくなります。
リアクティブ Web アプリケーションを構築する場合、次のストアを自動構成できます。
Redis
MongoDB
リアクティブ自動構成は、@Enable*WebSession
を使用する必要性を置き換えます。
単一の Spring Session モジュールがクラスパスに存在する場合、Spring Boot はそのストア実装を自動的に使用します。実装が複数ある場合は、セッションの保存に使用する StoreType
[GitHub] (英語) を選択する必要があります。たとえば、JDBC をバックエンドストアとして使用するには、次のようにアプリケーションを構成できます。
spring.session.store-type=jdbc
spring:
session:
store-type: "jdbc"
store-type を none に設定することにより、Spring Session を無効にできます。 |
各ストアには特定の追加設定があります。たとえば、次の例に示すように、JDBC ストアのテーブルの名前をカスタマイズできます。
spring.session.jdbc.table-name=SESSIONS
spring:
session:
jdbc:
table-name: "SESSIONS"
セッションのタイムアウトを設定するには、spring.session.timeout
プロパティを使用できます。そのプロパティがサーブレット Web アプリケーションで設定されていない場合、自動構成は server.servlet.session.timeout
の値にフォールバックします。
@Enable*HttpSession
(サーブレット)または @Enable*WebSession
(リアクティブ)を使用して、Spring Session の構成を制御できます。これにより、自動構成がバックオフします。Spring Session は、前述の構成プロパティではなく、アノテーションの属性を使用して構成できます。
6. Spring HATEOAS
ハイパーメディアを利用する RESTful API を開発する場合、Spring Boot は、ほとんどのアプリケーションで適切に機能する Spring HATEOAS の自動構成を提供します。自動構成は、@EnableHypermediaSupport
を使用する必要性を置き換え、ハイパーメディアベースのアプリケーションの構築を容易にするために多数の Bean を登録します。これには、LinkDiscoverers
(クライアント側サポート用)や、レスポンスを目的の表現に正しくマーシャリングするように構成された ObjectMapper
が含まれます。ObjectMapper
は、さまざまな spring.jackson.*
プロパティを設定するか、存在する場合は Jackson2ObjectMapperBuilder
Bean によってカスタマイズされます。
@EnableHypermediaSupport
を使用して、Spring HATEOAS の構成を制御できます。これを行うと、前述の ObjectMapper
のカスタマイズが無効になることに注意してください。
spring-boot-starter-hateoas は Spring MVC に固有であり、Spring WebFlux と組み合わせないでください。Spring HATEOAS を Spring WebFlux と一緒に使用するために、spring-boot-starter-webflux とともに org.springframework.hateoas:spring-hateoas への直接依存関係を追加できます。 |
7. 次のステップ
これで、Spring Boot を使用して Web アプリケーションを開発する方法を十分に理解できたはずです。次のいくつかのセクションでは、Spring Boot がさまざまなデータテクノロジー、メッセージングシステム、およびその他の IO 機能とどのように統合されるかについて説明します。アプリケーションのニーズに基づいて、これらのいずれかを選択できます。