Spring @ResponseBodyアノテーションはどのように機能しますか?


89

次のように注釈が付けられたメソッドがあります。

/**
* 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)

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

このメソッドは、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の結果が得られるはず です

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

このアサーションがtrueの場合、オブジェクトが自動的にJSONフォーマットに変換されることはどこに指定されていますか?@ResponseBodyアノテーションの使用時に標準形式が採用されていますか、それとも他の場所で指定されていますか?

回答:


160

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

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

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

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


3
こんにちは、「インストールされたメッセージコンバーター」の設定方法を教えてください。デフォルトを常にJsonに変換する必要があります。できますか?
GMsoF 2016

@JB Nizetでは、http応答にJavaオブジェクトを含めることができない理由を説明してください。私はJavaの初心者です。
Naved Ali

3
@ Er.NavedAliはhttp仕様を読み取り、http応答コンテンツタイプは、http応答に含めることができる正当なコンテンツを定義します。その有効な値は「application / octet-stream」、「image / jpeg」、「text / HTML」ですが、Javaオブジェクトは有効な値ではありません。
ZhaoGang 2016年

@ ZhaoGang、Content-type 'application / json'は私のテストケースで 'application / xml'に置き換えられましたが、応答本文は変更されていないようですが、まだjson形式が存在します。
LeafiWan 2016年

1
正確には、どの春のクラスで、どのように応答を返すかを決定する決定がなされたということですか この決定が行われるgithubまたはクラス名のソースを私に示すことができますか?また、クライアントがXMLを受け入れても、XMLコンバーターがインストールされていない場合はどうなりますか?
anir

63

最初に理解する必要があるのは、アーキテクチャの違いです。

一方の端には、通常のWebアプリに基づくMVCアーキテクチャがあり、Webページを使用しており、ブラウザがページをリクエストします。

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

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

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

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

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

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

コンテンツタイプを設定しますが、おそらくJSONがデフォルトです。引用しないでください。ただし、JSONを取得していてproduces、を指定していない場合は、おそらくそれがデフォルトです。JSONだけがフォーマットではありません。たとえば、上記はXMLで簡単に送信できますが、producesto MediaType.APPLICATION_XML_VALUEが必要でありHttpMessageConverter、JAXB用にを設定する必要があると思います。MappingJacksonHttpMessageConverter構成されたJSON に関しては、クラスパスにJacksonがある場合。

コンテンツネゴシエーションについて学ぶには、少し時間がかかります。RESTの非常に重要な部分です。さまざまな応答形式と、それらをメソッドにマップする方法について学習するのに役立ちます。


を使用せずに汎用/動的RESTコントローラーを作成する方法の調査中に答えが見つかった場合@Controller/@RestController。なんとかしてビューリゾルバーレイヤーを省略する必要があることがわかりました。AbstractControllerクラスはビュー名を返す必要があるメソッドを提供するため、それほど単純ではありません。私はそれについて質問しました:stackoverflow.com/questions/41016018/…、私の問題を解決する方法についていくつかのアイデアがある場合は、コメントを投稿してください。
nowszy94 2016

1

さらに、戻り値の型は次のように決定されます

  1. HTTPリクエストが望んでいること-Acceptヘッダー内。Acceptが何に設定されているかを確認しながら、最初のリクエストを確認してください。

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

選択肢がある場合は、1つを選択します。この例では、たまたまJSONです。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.