Jacksonと一緒のSpring JSON-P

JacksonのSpring JSON-P

1. 概要

Webで何かを開発している場合は、AJAXリクエストを処理するときにブラウザが持つthe same-origin policy constraintを知っています。 制約の簡単な概要は、異なるドメイン、スキーマ、またはポートから発信されるリクエストは許可されないということです。

JSONデータを操作するときにrelax this browser restrictionを実行する1つの方法は、パディング(JSON-P)を使用してJSONを使用することです。

この記事では、AbstractJsonpResponseBodyAdviceを使用して、JSON-Pデータを操作するためのSpringのサポートについて説明します。

2. JSON-Pの動作

<script>タグには同一生成元ポリシーが課されていないため、異なるドメイン間でスクリプトをロードできます。 JSON-P技術は、JSON応答をjavascript関数の引数として渡すことでこれを利用します。

2.1. 準備

この例では、次の単純なCompanyクラスを使用します。

public class Company {

    private long id;
    private String name;

    // standard setters and getters
}

このクラスは要求パラメーターをバインドし、JSON表現としてサーバーから返されます。

Controllerメソッドも単純な実装であり、Companyインスタンスを返します。

@RestController
public class CompanyController {

    @RequestMapping(value = "/companyRest",
      produces = MediaType.APPLICATION_JSON_VALUE)
    public Company getCompanyRest() {
        Company company = new Company(1, "Xpto");
        return company;
    }
}

クライアント側では、jQueryライブラリを使用してAJAXリクエストを作成して送信できます。

$.ajax({
    url: 'http://localhost:8080/spring-mvc-java/companyRest',
    data: {
        format: 'json'
    },
    type: 'GET',
    ...
});

次のURLに対するAJAXリクエストを検討してください。

http://localhost:8080/spring-mvc-java/companyRest

サーバーからの応答は次のようになります。

{"id":1,"name":"Xpto"}

リクエストは同じスキーマ、ドメイン、ポートに対して送信されたため、レスポンスはブロックされず、JSONデータはブラウザで許可されます。

2.2. クロスオリジンリクエスト

リクエストURLを次のように変更します。

http://127.0.0.1:8080/spring-mvc-java/companyRest

リクエストがlocalhostから127.0.0.1に送信されたため、応答はブラウザによってブロックされます。これは、別のドメインと見なされ、同一生成元ポリシーの違反を示します。

JSON-Pを使用すると、リクエストにコールバックパラメーターを追加できます。

http://127.1.1.1:8080/spring-mvc-java/companyRest?callback=getCompanyData

クライアント側では、AJAXリクエストに次のパラメータを追加するのと同じくらい簡単です。

$.ajax({
    ...
    jsonpCallback:'getCompanyData',
    dataType: 'jsonp',
    ...
});

getCompanyDataは、応答を受信したときに呼び出される関数になります。

サーバーが応答を次のようにフォーマットする場合:

getCompanyData({"id":1,"name":"Xpto"});

要求と応答の両方でgetCompanyDataが一致するため、クライアントとサーバー間でネゴシエートおよび合意されたスクリプトとして応答を処理するため、ブラウザはそれをブロックしません。

3. @ControllerAdvice注釈

@ControllerAdviceで注釈が付けられたBeanは、コントローラーのすべてまたは特定のサブセットを支援することができ、異なるコントローラー間で共有される横断的な動作をカプセル化するために使用されます。 一般的な使用パターンは、exception handlingadding attributes to models、またはバインダーの登録に関連しています。

Starting with Spring 4.1@ControllerAdviceは、ResponseBodyAdviceインターフェイスの実装を登録できます。これにより、コントローラーメソッドによって返された後、適切なコンバーターによって書き込まれる前に、応答を変更できます。

4. AbstractJsonpResponseBodyAdviceを使用した応答の変更

Also starting with Spring 4.1、これでAbstractJsonpResponseBodyAdviceクラスにアクセスできるようになりました。これはJSON-P標準に従って応答をフォーマットします。

このセクションでは、基本クラスを実行し、既存のコントローラーを変更せずに応答を変更する方法について説明します。

JSON-PのSpringサポートを有効にするために、設定から始めましょう:

@ControllerAdvice
public class JsonpControllerAdvice
  extends AbstractJsonpResponseBodyAdvice {

    public JsonpControllerAdvice() {
        super("callback");
    }
}

サポートは、AbstractJsonpResponseBodyAdviceクラスを使用して行われます。 スーパーメソッドに渡されるキーは、JSON-Pデータを要求するURLで使用されるキーです。

このコントローラーのアドバイスを使用して、応答をJSON-Pに自動的に変換します。

5. Springを実際に使用したJSON-P

前に説明した構成が用意されていれば、RESTアプリケーションにJSON-Pで応答させることができます。 次の例では、会社のデータを返すため、AJAXリクエストURLは次のようになります。

http://127.0.0.1:8080/spring-mvc-java/companyRest?callback=getCompanyData

前の構成の結果、応答は次のようになります。

getCompanyData({"id":1,"name":"Xpto"});

説明したように、この形式の応答は、異なるドメインから発信されているにもかかわらずブロックされません。

JsonpControllerAdviceは、@ResponseBodyおよびResponseEntityで注釈が付けられた応答を返す任意のメソッドに簡単に適用できます。

すべての応答を処理するために、コールバックで渡される同じ名前の関数getCompanyDataが必要です。

6. 結論

この簡単な記事では、JSON-Pを利用するためにレスポンスをフォーマットするという面倒な作業が、Spring 4.1の新しい機能を使用してどのように簡素化されるかを示します。

例とコードスニペットの実装は、このGitHub projectにあります。