Spring MVCのコンテンツネゴシエーション

1概要

この記事では、Spring MVCプロジェクトでコンテンツネゴシエーションを実装する方法について説明します。

一般に、要求のメディアタイプを決定するための3つのオプションがあります。

  • リクエストでURLサフィックス(拡張子)を使う(例: .xml/.json

  • リクエストでURLパラメータを使用する(例: ?format = json

  • リクエストで Accept ヘッダを使う

デフォルトでは、これはSpringコンテンツネゴシエーションマネージャがこれら3つの戦略を使用しようとする順番です。そして、これらがどれも有効になっていない場合は、デフォルトのコンテンツタイプへのフォールバックを指定できます。

2コンテンツネゴシエーション戦略

必要な依存関係から始めましょう - 私たちはJSONとXML表現を使っているので、この記事ではJackson for JSONを使います。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.7.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.7.2</version>
</dependency>

XMLサポートには、JAXB、XStream、または新しいJackson-XMLサポートのいずれかを使用できます。

link:/spring-httpmessageconverter-rest HttpMessageConverters での Accept ヘッダーの使用について説明したので、 最初の2つの戦略について詳しく説明しましょう。

** 3 URLサフィックス戦略

**

デフォルトでは、この方法は無効になっていますが、フレームワークはURLから直接パスの拡張子を確認して、出力コンテンツタイプを判断できます。

構成に入る前に、例を簡単に見てみましょう。

一般的なSpringコントローラには、次のような単純なAPIメソッドの実装があります。

@RequestMapping(
  value = "/employee/{id}",
  produces = { "application/json", "application/xml" },
  method = RequestMethod.GET)
public @ResponseBody Employee getEmployeeById(@PathVariable long id) {
    return employeeMap.get(id);
}

JSONエクステンションを使ってリソースのメディアタイプを指定して呼び出します。

curl http://localhost:8080/spring-mvc-java/employee/10.json

JSONエクステンションを使用すると、以下のようになります。

{
    "id": 10,
    "name": "Test Employee",
    "contactNumber": "999-999-9999"
}

そして、要求と応答がXMLでどのようになるかを次に示します。

curl http://localhost:8080/spring-mvc-java/employee/10.xml

レスポンスボディ:

<employee>
    <contactNumber>999-999-9999</contactNumber>
    <id>10</id>
    <name>Test Employee</name>
</employee>

今:

拡張機能を使用していない場合や、設定されていない拡張機能を使用している場合は、デフォルトのコンテンツタイプが返されます。

curl http://localhost:8080/spring-mvc-java/employee/10

それでは、JavaとXMLの両方の構成を使用して、この戦略を設定しましょう。

3.1. Javaの設定

public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(true).
    favorParameter(false).
    ignoreAcceptHeader(true).
    useJaf(false).
    defaultContentType(MediaType.APPLICATION__JSON);
}

詳細を見てみましょう。

まず、パス拡張戦略を有効にします。

次に、URLパラメータストラテジと Accept ヘッダストラテジを無効にします。これは、コンテンツの種類を判断するためのパス拡張方法にのみ依存するためです。

それから、Java Activation Frameworkをオフにします。着信要求が設定した戦略のいずれとも一致しない場合、JAFを出力形式を選択するためのフォールバックメカニズムとして使用できます。 JSONをデフォルトのコンテンツタイプとして設定するので、無効にしています。

そして最後に、JSONをデフォルトに設定しています。つまり、2つの戦略のいずれも一致しない場合、すべての着信要求はJSONを処理するコントローラメソッドにマッピングされます。

3.2. XML設定

XMLのみを使用して、まったく同じ構成を簡単に見てみましょう。

<bean id="contentNegotiationManager"
  class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="true"/>
    <property name="favorParameter" value="false"/>
    <property name="ignoreAcceptHeader" value="true"/>
    <property name="defaultContentType" value="application/json"/>
    <property name="useJaf" value="false"/>
</bean>

** 4 URLパラメータ戦略

**

前のセクションではパス拡張を使用しました - パスパラメータを使用するようにSpring MVCを設定しましょう。

この戦略を有効にするには、 favorParameter プロパティの値をtrueに設定します。

前の例でどのように機能するかを簡単に見てみましょう。

curl http://localhost:8080/spring-mvc-java/employee/10?mediaType=json

JSONレスポンスボディは次のようになります。

{
    "id": 10,
    "name": "Test Employee",
    "contactNumber": "999-999-9999"
}

XMLパラメータを使用すると、出力はXML形式になります。

curl http://localhost:8080/spring-mvc-java/employee/10?mediaType=xml

レスポンスボディ:

<employee>
    <contactNumber>999-999-9999</contactNumber>
    <id>10</id>
    <name>Test Employee</name>
</employee>

それでは、最初にJavaを使用してからXMLを使用して、設定を行いましょう。

4.1. Javaの設定

public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(false).
    favorParameter(true).
    parameterName("mediaType").
    ignoreAcceptHeader(true).
    useJaf(false).
    defaultContentType(MediaType.APPLICATION__JSON).
    mediaType("xml", MediaType.APPLICATION__XML).
    mediaType("json", MediaType.APPLICATION__JSON);
}

この設定を読みましょう。

まず最初に、もちろんパス拡張と Accept ヘッダー戦略は無効になっています(JAFと同様に)。

その他の構成は同じです。

4.2. XML設定

<bean id="contentNegotiationManager"
  class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false"/>
    <property name="favorParameter" value="true"/>
    <property name="parameterName" value="mediaType"/>
    <property name="ignoreAcceptHeader" value="true"/>
    <property name="defaultContentType" value="application/json"/>
    <property name="useJaf" value="false"/>

    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json"/>
            <entry key="xml" value="application/xml"/>
        </map>
    </property>
</bean>

また、両方の戦略(拡張とパラメータ)を同時に有効にすることもできます。

public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(true).
    favorParameter(true).
    parameterName("mediaType").
    ignoreAcceptHeader(true).
    useJaf(false).
    defaultContentType(MediaType.APPLICATION__JSON).
    mediaType("xml", MediaType.APPLICATION__XML).
    mediaType("json", MediaType.APPLICATION__JSON);
}

この場合、Springは最初にパス拡張を探します。それが存在しない場合は、次にパスパラメータを探します。そして、これら両方が入力要求で利用できない場合は、デフォルトのコンテンツタイプが返されます。

** 5 Acceptヘッダー戦略

**

Accept ヘッダーが有効になっている場合、Spring MVCは受信リクエストでその値を探して表現タイプを決定します。

このアプローチを有効にするには、 ignoreAcceptHeader の値をfalseに設定する必要があります。他の2つの戦略は無効にしているため、 Accept ヘッダーのみに依存していることがわかります。

5.1. Javaの設定

public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(true).
    favorParameter(false).
    parameterName("mediaType").
    ignoreAcceptHeader(false).
    useJaf(false).
    defaultContentType(MediaType.APPLICATION__JSON).
    mediaType("xml", MediaType.APPLICATION__XML).
    mediaType("json", MediaType.APPLICATION__JSON);
}

5.2. XML設定

<bean id="contentNegotiationManager"
  class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="true"/>
    <property name="favorParameter" value="false"/>
    <property name="parameterName" value="mediaType"/>
    <property name="ignoreAcceptHeader" value="false"/>
    <property name="defaultContentType" value="application/json"/>
    <property name="useJaf" value="false"/>

    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json"/>
            <entry key="xml" value="application/xml"/>
        </map>
    </property>
</bean>

最後に、コンテンツネゴシエーションマネージャを全体設定にプラグインすることでオンにする必要があります。

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>

6. 結論

これで終わりです。 Spring MVCでのコンテンツネゴシエーションがどのように機能するかを調べ、コンテンツタイプを決定するためにさまざまな戦略を使用するように設定するいくつかの例に焦点を当てました。

この記事の完全な実装はhttps://github.com/eugenp/tutorials/tree/master/spring-mvc-java[the github project]にあります。これはEclipseベースのプロジェクトなので、簡単に実行できます。そのままインポートして実行します。

前の投稿:Java - リストからランダムなアイテム/要素を取得する
次の投稿:jOOLの紹介