Spring MVC

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

JSON REST サービスを作成する

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

  • Java

  • Kotlin

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

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

}
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class MyController {

	@RequestMapping("/thing")
	fun thing(): MyThing {
		return MyThing()
	}

}

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

XML REST サービスを作成する

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

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

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

  • Java

  • Kotlin

import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class MyThing {

	private String name;

	// getters/setters ...

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
import jakarta.xml.bind.annotation.XmlRootElement

@XmlRootElement
class MyThing {

	var name: String? = null

}

たとえば、次を追加して、JAXB ライブラリがプロジェクトの一部であることを確認する必要があります。

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

Jackson ObjectMapper をカスタマイズする

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

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

  • MapperFeature.DEFAULT_VIEW_INCLUSION は無効です

  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES は無効です

  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS は無効です

  • SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS は無効です

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

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

列挙型 プロパティ

com.fasterxml.jackson.databind.cfg.EnumFeature

spring.jackson.datatype.enum.<feature_name>

true, false

com.fasterxml.jackson.databind.cfg.JsonNodeFeature

spring.jackson.datatype.json-node.<feature_name>

true, false

com.fasterxml.jackson.databind.DeserializationFeature

spring.jackson.deserialization.<feature_name>

true, false

com.fasterxml.jackson.core.JsonGenerator.Feature

spring.jackson.generator.<feature_name>

true, false

com.fasterxml.jackson.databind.MapperFeature

spring.jackson.mapper.<feature_name>

true, false

com.fasterxml.jackson.core.JsonParser.Feature

spring.jackson.parser.<feature_name>

true, false

com.fasterxml.jackson.databind.SerializationFeature

spring.jackson.serialization.<feature_name>

true, false

com.fasterxml.jackson.annotation.JsonInclude.Include

spring.jackson.default-property-inclusion

always, non_null, non_absent, non_default, non_empty

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Spring MVC DispatcherServlet をオフにする

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

  • プロパティ

  • YAML

spring.mvc.servlet.path=/mypath
spring:
  mvc:
    servlet:
      path: "/mypath"

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

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

デフォルトの MVC 設定をオフにします

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

ViewResolvers をカスタマイズする

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

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

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

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

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

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

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

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

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

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