49.4. 要求と応答の解析
概要
HTTP 呼び出しを行う際の重要な側面は、クライアントが送信要求メッセージと受信応答を解析できる必要があることです。JAX-RS 2.0 では、主要な概念は、メディアタイプでタグ付けされた raw メッセージを表す Entity
クラスです。未加工メッセージを解析するために、メディアタイプと特定の Java タイプとの間で変換できる複数の エンティティープロバイダー を登録できます。
つまり、JAX-RS 2.0 のコンテキストでは、Entity
は raw メッセージの表現で、エンティティープロバイダーは (メディア型に基づく) raw メッセージを解析する機能を提供するプラグインです。
Entities
Entity
は、メタデータ (メディア型、言語、およびエンコーディング) によって拡張されたメッセージボディーです。Entity
インスタンスはメッセージを raw 形式で保持し、特定のメディア型に関連付けられます。Entity
オブジェクトのコンテンツを、Java オブジェクトに変換するには、指定のメディア型を必要な Java 型にマッピングできる エンティティープロバイダー が必要です。
バリアント
javax.ws.rs.core.Variant
オブジェクトは、以下のように Entity
に関連付けられたメタデータをカプセル化します。
- メディアタイプ
- 言語
- エンコーディング
実質的に、Entity
は HTTP メッセージの内容で構成され、Variant
メタデータによって拡張されると考えることができます。
エンティティープロバイダー
エンティティープロバイダーは、メディアタイプと Java 型間のマッピング機能を提供するクラスです。実際には、エンティティープロバイダーは、特定のメディアタイプ (または複数のメディアタイプ) のメッセージを解析できるクラスと考えることができます。エンティティープロバイダーには、以下の 2 つの異なるバリアントがあります。
MessageBodyReader
- メディアタイプから Java 型へのマッピング機能を提供します。
MessageBodyWriter
- Java 型からメディアタイプへのマッピング機能を提供します。
標準のエンティティープロバイダー
次の Java とメディアタイプの組み合わせのエンティティープロバイダーが標準として提供されています。
byte[]
-
すべてのメディア型 (
*/*
) java.lang.String
-
すべてのメディア型 (
*/*
) java.io.InputStream
-
すべてのメディア型 (
*/*
) java.io.Reader
-
すべてのメディア型 (
*/*
) java.io.File
-
すべてのメディア型 (
*/*
) javax.activation.DataSource
-
すべてのメディア型 (
*/*
) javax.xml.transform.Source
-
XML 型 (
text/xml
、application/xml
、およびapplication/*+xml
フォームのメディア型)。 javax.xml.bind.JAXBElement
およびアプリケーションが提供する JAXB クラス-
XML 型 (
text/xml
、application/xml
、およびapplication/*+xml
フォームのメディア型)。 MultivaluedMap<String,String>
-
フォームコンテンツ (
application/x-www-form-urlencoded
)。 StreamingOutput
-
すべてのメディア型 (
*/*
)、MessageBodyWriter
のみ。 java.lang.Boolean
、java.lang.Character
、java.lang.Number
-
text/plain
のみ対象。ボックス/アンボックス変換でサポートされるプリミティブタイプ。
Response オブジェクト
デフォルトの戻り値型は javax.ws.rs.core.Response
型で、型付けされていない応答を表します。Response
オブジェクトは、メッセージボディー、HTTP ステータス、HTTP ヘッダー、メディア型など、完全な HTTP 応答へのアクセスを提供します。
応答ステータスへのアクセス
応答の状態には、getStatus
メソッド (HTTP ステータスコードを返す) からアクセスできます。
int status = resp.getStatus();
または、説明文字列も提供する getStatusInfo
メソッドでアクセスすることもできます。
String statusReason = resp.getStatusInfo().getReasonPhrase();
返されるヘッダーへのアクセス
以下の方法のいずれかを使用して HTTP ヘッダーにアクセスできます。
MultivaluedMap<String,Object> getHeaders() MultivaluedMap<String,String> getStringHeaders() String getHeaderString(String name)
たとえば、Response
に Date
ヘッダーがあることが分かっている場合は、以下のようにアクセスできます。
String dateAsString = resp.getHeaderString("Date");
返されるクッキーへのアクセス
以下のように、getCookies
メソッドを使用して、Response
で設定された新しいクッキーにアクセスできます。
import javax.ws.rs.core.NewCookie; ... java.util.Map<String,NewCookie> cookieMap = resp.getCookies(); java.util.Collection<NewCookie> cookieCollection = cookieMap.values();
返されるメッセージコンテンツへのアクセス
Response
オブジェクトの readEntity
メソッドのいずれかを呼び出すと、返されるメッセージコンテンツにアクセスできます。readEntity
メソッドは利用可能なエンティティープロバイダーを自動的に呼び出し、メッセージを要求された型 (readEntity
の最初の引数として指定) に変換します。たとえば、メッセージコンテンツに String
型としてアクセスするには、次のように指定します。
String messageBody = resp.readEntity(String.class);
コレクションの戻り値
返されたメッセージを Java 汎用型 (例: List
または Collection
型) としてアクセスする必要がある場合、javax.ws.rs.core.GenericType<T>
コンストラクションを使用してリクエストメッセージ型を指定できます。以下に例を示します。
import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Client; import javax.ws.rs.core.GenericType; import java.util.List; ... GenericType<List<String>> stringListType = new GenericType<List<String>>() {}; Client client = ClientBuilder.newClient(); List<String> bookNames = client.target("http://example.org/bookstore/booknames") .request("text/plain") .get(stringListType);