web-dev-qa-db-ja.com

このRESTfulアプリケーションの例では、Spring @ResponseBodyアノテーションはどのように機能しますか?

私は以下のようにアノテーションが付けられたメソッドを持っています:

/**
* Provide a list of all accounts.
*/
//  TODO 02: Complete this method.  Add annotations to respond
//  to GET /accounts and return a List<Account> to be converted.
//  Save your work and restart the server.  You should get JSON results when accessing 
//  http://localhost:8080/rest-ws/app/accounts
@RequestMapping(value="/orders", method=RequestMethod.GET)
public @ResponseBody List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

だから私はこのアノテーションによってそれを知っています:

@RequestMapping(value="/orders", method=RequestMethod.GET)

このメソッドはGET URLで表されるリソースに対して行われたHTTPリクエスト/ ordersを処理します。

このメソッドは、Listを返すDAOオブジェクトを呼び出します。

ここでAccountはシステム上のユーザーを表し、このユーザーを表すフィールドがいくつかあります。

public class Account {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long entityId;

    @Column(name = "NUMBER")
    private String number;

    @Column(name = "NAME")
    private String name;

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name = "ACCOUNT_ID")
    private Set<Beneficiary> beneficiaries = new HashSet<Beneficiary>();

    ...............................
    ...............................
    ...............................
}

私の質問は次のとおりです。@ResponseBodyアノテーションはどのように機能しますか?

これは返されたList<Account>オブジェクトの前にあるので、このリストを参照していると思います。コースのドキュメントには、このアノテーションが以下の機能を果たすと記載されています。

結果が(MVCビューではなく)HTTPメッセージコンバータによってHTTP応答に書き込まれるようにします。

また、公式のSpringドキュメントも読んでください。 http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ResponseBody.html

List<Account>オブジェクトを受け取り、それをHttp Responseに入れるようです。これは正しいですか、それとも私は誤解していますか?

前のaccountSummary()メソッドのコメントに書かれています:

http:// localhost:8080/rest-ws/app/accounts にアクセスするとJSONの結果が得られます。

それで、これは正確にはどういう意味ですか? accountSummary()メソッドによって返されるList<Account>オブジェクトは自動的にJSONフォーマットに変換されてからHttp Responseに入れられるということですか?または何?

この主張が真実である場合、オブジェクトが自動的にJSON形式に変換されることがどこで指定されているのでしょうか。 @ResponseBodyアノテーションを使用するときに標準フォーマットが採用されていますか、それとも他の場所で指定されていますか?

80
AndreaNobili

まず第一に、アノテーションはListをアノテーションしません。 RequestMappingと同じように、メソッドに注釈を付けます。あなたのコードは

@RequestMapping(value="/orders", method=RequestMethod.GET)
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

アノテーションの意味するところは、メソッドの戻り値がHTTPレスポンスの本体を構成するということです。もちろん、HTTPレスポンスにJavaオブジェクトを含めることはできません。そのため、このアカウントのリストはRESTアプリケーションに適した形式(通常はJSONまたはXML)に変換されます。

形式の選択は、インストールされているメッセージコンバータ、RequestMappingアノテーションの produces attribute の値、およびクライアントが受け付けるコンテンツタイプ(HTTP要求ヘッダーで利用可能)によって異なります。 。たとえば、リクエストがXMLを受け入れるがJSONは受け付けないと言っていて、リストをXMLに変換できるメッセージコンバータがインストールされている場合、XMLが返されます。

135
JB Nizet

理解するべき最初の基本的なことはアーキテクチャの違いです。

一方の端にはMVCアーキテクチャがあります。これは通常のWebアプリケーションに基づいており、Webページを使用しています。ブラウザがページを要求します。

Browser <---> Controller <---> Model
               |      |
               +-View-+

ブラウザが要求を出し、コントローラ(@Controller)がモデル(@Entity)を取得し、そのモデルからビュー(JSP)を作成し、そのビューがクライアントに返されます。これが基本的なWebアプリのアーキテクチャです。

反対に、あなたはRESTfulなアーキテクチャを持っています。この場合、ビューはありません。コントローラーはモデル(またはより多くのRESTfulな用語ではリソース表現)のみを返送します。クライアントは、JavaScriptアプリケーション、Javaサーバーアプリケーション、およびREST AP​​Iを公開する任意のアプリケーションにすることができます。このアーキテクチャでは、クライアントはこのモデルをどうするかを決定します。例えばTwitterを見てください。 Web(REST)APIとしてのTwitter。これを使用すると、アプリケーションはそのAPIを使用してステータスの更新などを取得できるので、そのデータをアプリケーションに含めることができます。そのデータはJSONのような何らかのフォーマットになります。

とは言っても、Spring MVCを使用するとき、最初に基本的なWebアプリケーションアーキテクチャを処理するために構築されました。私たちのメソッドからビューを生成することを可能にするさまざまなメソッドシグネチャフレーバーがあります。このメソッドは明示的に作成したModelAndViewを返すことも、モデル属性に設定された任意のオブジェクトを返すことができる暗黙の方法もあります。しかし、どちらにしても、要求 - 応答サイクルの途中のどこかで、ビューが作成されます。

しかし、私たちが@ResponseBodyを使うとき、私たちはビューを作りたくないと言っています。指定した形式で、返り値オブジェクトを本文として送信するだけです。それを直列化されたJavaオブジェクトにしたくありません(可能ですが)。そのため、他の一般的なタイプに変換する必要があります(このタイプは通常、コンテンツネゴシエーションを通じて処理されます - 下記のリンクを参照)。正直なところ、私はSpringをあまり問題にしていません。通常は

@RequestMapping(..., produces = MediaType.APPLICATION_JSON_VALUE)

コンテンツタイプを設定しますが、JSONがデフォルトである可能性があります。私を引用しないでください、しかし、あなたがJSONを得ている、そしてあなたがproducesを指定していないならば、それは多分それはデフォルトです。 JSONが唯一のフォーマットではありません。たとえば、上記はXMLで簡単に送信できますが、producesMediaType.APPLICATION_XML_VALUEにする必要があり、JAXB用にHttpMessageConverterを構成する必要があると思います。 JSONのMappingJacksonHttpMessageConverterが構成されているのは、Jacksonがクラスパスにいるときです。

私は コンテンツネゴシエーション について学ぶのに時間がかかるでしょう。これはRESTの非常に重要な部分です。さまざまなレスポンスフォーマットについて学び、それらを自分のメソッドにマッピングする方法を学ぶのに役立ちます。

52
Paul Samsotha

JB Nizetが述べたように、

@RequestMapping(value="/orders", method=RequestMethod.GET)
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

そして

@RequestMapping(value="/orders", method=RequestMethod.GET)
public @ResponseBody List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

両方とも同じです。 @ResponseBodyはリストではなくメソッドに注釈を付けます。ここで@GMsoFがインストールされているメッセージコンバータは、次のように使用できます。

@RequestMapping(value="/orders", method=RequestMethod.GET , produces={"application/json","application/xml"})
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

ありがとう:)

4
Nupur

これに加えて、戻り型は次のように決定されます。

  1. HTTPリクエストがそれを望んでいると言うもの - そのAcceptヘッダに。 Acceptが設定されているものを見るように最初のリクエストを見てみてください。

  2. HttpMessageConverters Springがセットアップするもの。 Jacksonライブラリがクラスパスにある場合、Spring MVCはXML(JAXBを使用)とJSON用のコンバータをセットアップします。

選択するものがあれば、それを選択します - この例では、それは偶然JSONです。

これはisコースノートに含まれています。メッセージコンバータとコンテンツネゴシエーションに関するメモを探してください。

1
paulchapman