Oracle® Fusion Middleware Oracle WebLogic Server RESTful Webサービスの開発と保護 12c (12.2.1) E69940-01 |
|
前 |
次 |
この章では、Java API for RESTful Web Services (JAX-RS)を使用して、Representational State Transfer (REST)アーキテクチャ・スタイルに従ったJava EE Webサービスを開発する方法について説明します。
この章の内容は次のとおりです:
JAX-RSは、アノテーションを使用して、RESTful Webサービスの開発を簡略化するJavaプログラミング言語APIです。JAX-RSアノテーションは実行時アノテーションです。JAX-RSリソース・クラスを含むJava EEアプリケーション・アーカイブをWebLogic Serverにデプロイする場合(第4章「RESTful Webサービス・アプリケーションの構築、パッケージ化およびデプロイ」を参照)、ランタイムによってリソースの構成、ヘルパー・クラスおよびアーティファクトの生成、クライアントへのリソースの公開が行われます。
次の各項で、RESTful Webサービスの開発について詳しく説明します。
Oracle JDeveloperを使用したRESTful Webサービスの開発の詳細は、『Oracle JDeveloperによるアプリケーションの開発』のRESTful Webサービスおよびクライアントの作成に関する項を参照してください。
表2-1に、JAX-RSアノテーションを使用してRESTful Webサービスを開発する場合に必要なタスクのサブセットの概要を示します。高度なタスクの詳細は、「高度なRESTful Webサービス・タスク」を参照してください。
注意: 表2-1で説明されている開発タスクに加えて、RESTful Webサービスの開発時にJersey 2.x (JAX-RS 2.0 RI)で使用できる機能の利用が必要になることもあります。主な機能のリストは、表1-2「Jersey 2.x (JAX-RS 2.0 RI)の主な機能」を参照してください。 |
表2-1 RESTful Webサービスを開発するタスクの概要
タスク | 詳細情報 |
---|---|
ルート・リソース・クラスを定義します。 |
|
変数を使用して |
|
|
|
必要に応じて、リクエストおよびレスポンス・メッセージをカスタマイズして、リソースが生成および消費できるMIMEメディア・タイプを指定します。 |
リクエスト・メッセージおよびレスポンス・メッセージのメディア・タイプのカスタマイズ |
リクエストから情報を抽出します。 |
|
レスポンス・コードをカスタマイズする、または追加メタデータを含めるためのカスタム・レスポンス・メッセージを構築します。 |
|
アプリケーション・デプロイメント・コンテキストまたは個別リクエストのコンテキストに関する情報にアクセスします。 |
|
新規のリソースURIを構築、または既存のリソースURIを拡張します。 |
|
GETリクエストの処理前に1つ以上の前条件を評価することで、潜在的に帯域幅を縮小し、サーバー・パフォーマンスを改善します。 |
|
WADLにアクセスします。 |
|
必要に応じて、 |
|
RESTful Webサービスを保護します。 |
第5章「RESTful Webサービスとクライアントの保護」 |
例2-1に、RESTful Webサービスの簡単な例を示します。この例の内容は次のとおりです。
helloWorld
クラスは/helloworld
として定義された相対URIパスを含むリソースです。実行時に、WARファイルのコンテキスト・ルートがhttp://examples.com
として定義されている場合、リソースにアクセスするためのフルURIはhttp://examples.com/helloworld
です。詳細は、「ルート・リソースおよびサブリソースの相対URIの定義」を参照してください。
sayHello
メソッドはHTTP GETメソッドをサポートします。詳細は、「受信HTTPリクエストのJavaメソッドへのマッピング」を参照してください。
sayHello
メソッドはMIMEメディア・タイプtext/plain
のコンテンツを生成します。詳細は、「リクエスト・メッセージおよびレスポンス・メッセージのメディア・タイプのカスタマイズ」を参照してください。
追加の例を「RESTful Webサービスの詳細」に示します。
例2-1 簡単なRESTful Webサービスの例
package samples.helloworld; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; // Specifies the path to the RESTful service @Path("/helloworld") public class helloWorld { // Specifies that the method processes HTTP GET requests @GET @Produces("text/plain") public String sayHello() { return "Hello World!"; } }
ルート・リソース・クラスは、次の条件の1つまたは両方がtrueであるPlain Old Java Object (POJO)です。
@Path
でアノテーションが付けられている。詳細は、「ルート・リソースおよびサブリソースの相対URIの定義」を参照してください。
少なくとも1つのメソッドが@Path
、または@GET、@POST
、@PUT
、@DELETE
などのリクエスト・メソッド指定子
によりアノテーションが付けられている。リソース・メソッドはリクエスト・メソッド指定子を使用してアノテーションが付けられたリソース・クラスのメソッドです。詳細は、「受信HTTPリクエストのJavaメソッドへのマッピング」を参照してください。
リソースのクラス・レベルでjavax.ws.rs.Path
アノテーションを追加し、RESTful Webサービスの相対URIを定義します。このようなクラスはルート・リソース・クラスと呼ばれます。特定の機能をグループ化するためのサブリソースを定義するため、@Path
もルート・リソース・クラスのメソッドに追加できます。
次の項では、ルート・リソースおよびサブリソースの相対URIの定義方法について説明します。
@Path
アノテーションはリソースの相対URIを定義し、定数または変数(URIパス・テンプレートとして参照される)として定義できます。@Path
アノテーションをクラスまたはメソッド・レベルで追加できます。
URIを定数値として定義するには、定数値を@Path
アノテーションに渡します。先頭と末尾のスラッシュ(/)はオプションです。
例2-2では、リソース・クラスの相対URIが定数値/helloworld
として定義されます。
例2-2 相対URIの定数値としての定義
package samples.helloworld; import javax.ws.rs.Path; ... // Specifies the path to the RESTful service @Path("/helloworld") public class helloWorld {. . .}
URIをURIパス・テンプレートとして定義するには、1つまたは複数の変数値を@Path
アノテーションに中カッコで囲んで渡します。すると、javax.ws.rs.PathParam
アノテーションを使用して、@Path
アノテーションで定義されたリクエストURIから変数情報を抽出でき、メソッド・パラメータの値を初期化できます(変数情報をリクエストURI (@PathParam)から抽出する方法を参照)。
例2-3では、リソース・クラスの相対URIが、中かっこで囲まれた変数を使用して定義されます。たとえば、/users/{username}
です。
例2-3 相対URIの変数値としての定義
package samples.helloworld; import javax.ws.rs.Path; ... // Specifies the path to the RESTful service @Path("/users/{username}") public class helloWorld {. . .} }
変数をさらにカスタマイズするには、デフォルトの正規表現の"[^/]+?"を、変数定義の一部として必要な正規表現を指定することでオーバーライドできます。以下に例を示します。
@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]}")
この例では、username
変数は、1つの大文字または小文字で始まり、ゼロまたはそれ以上の英数字またはアンダースコア文字が続くユーザー名にのみ一致します。ユーザー名が要件に一致しない場合、404 (Not Found)
レスポンスがクライアントに送信されます。
詳細は、Java EE 7 API仕様の@Path
アノテーションを参照してください。
javax.ws.rs.Path
アノテーションをリソースのメソッドに追加して、サブリソースを定義します。サブリソースによってユーザーは、リソースに対する特定の機能をグループ化できます。
例2-3で、URIのリクエスト・パスがusers/list
の場合は、getUserList
サブリソース・メソッドが照合され、ユーザーのリストが返されます。
基底URIは次のように構成されます。
http://myHostName/contextPath/servletURI
/resourceURI
myHostName
— Web サーバーにマップされるDNS名。これを、WebLogic Serverを実行しているマシン名とリクエストのリスニングに使用するポートを指定するhost:port
で置き換えることができます。
contextPath
—スタンドアロンWebアプリケーションの名前。Webアプリケーション名はEARファイル内のMETA-INF/application.xml
デプロイメント記述子またはWARファイルのweblogic.xml
デプロイメント記述子に指定されます。指定されない場合、デフォルトはWARファイルから.war
拡張子を取り去った名前です。詳細は、『Oracle WebLogic Server Webアプリケーション、サーブレット、JSPの開発』のcontext-rootに関する項を参照してください。
servletURI
—サーブレットのコンテキスト・パスの基底URIです。このパスは、表4-1で定義されているパッケージ化オプションの一部として構成されます。特に、次を実行して、サーブレットのコンテキスト・パスを定義できます。
web.xml
デプロイメント記述子を更新して、サーブレット・マッピングを定義します。
javax.ws.rs.ApplicationPath
アノテーションをjavax.ws.rs.core.Application
を拡張するクラスに追加します(定義されている場合)。
サーブレットのコンテキスト・パスが上記のオプションの両方を使用して構成されている場合、サーブレット・マッピングが優先されます。前述のオプションのいずれかを使用して、構成内にサーブレットのコンテキスト・パスを構成しない場合、WebLogic ServerによってデフォルトのRESTful Webサービス・アプリケーションのコンテキスト・パスresources
が提供されます。詳細は、第4章「RESTful Webサービス・アプリケーションの構築、パッケージ化およびデプロイ」を参照してください。
resourceURI
—リソースまたはサブリソースに対して指定された@Path
値。このパスは、複数のリソースおよびサブリソースの@Path
値で構成されることがあります。
例2-2では、WARファイルに対するコンテキスト・パスがrest
として定義されていて、サーブレットのデフォルトURI (resources
)が有効な場合、実行時のリソースにアクセスする基底URIはhttp://myServer:7001/rest/resources/helloworld
です。
例2-3では、実行時に、基底URIは変数に対して指定された値に基づき構成されます。たとえば、ユーザーがユーザー名としてjohnsmith
を入力した場合、リソースにアクセスする基底URIはhttp://myServer:7001/rest/resources/users/johnsmith
です。
JAX-RSはJavaアノテーションを使用して受信HTTPリクエストをJavaメソッドにマッピングします。表2-2に、同じような名前が付けられたHTTPメソッドにマッピングする、使用可能なアノテーションを示します。
表2-2 HTTPリクエストのJavaメソッドへのマッピング用javax.ws.rsアノテーション
アノテーション | 説明 | 多重呼出し不変 |
---|---|---|
|
URIにより識別されるリソースの表現をクライアントに送信します。フォーマットは、HTML、プレーン・テキスト、JPEGなどです。「リソースの表現の送信方法(@GET)」を参照してください。 |
はい |
|
URIで識別された特定のリソースの表現を作成または更新します。「リソースの表現の作成または更新方法(@PUT)」を参照してください。 |
はい |
|
URIで識別されたリソースの表現を削除します。「リソースの表現の削除方法(@DELETE)」を参照してください。 |
はい |
|
URIで識別された特定のリソースの表現でのアクションを作成、更新、または実行します。「リソースの表現でのアクションの作成、更新または実行方法(@POST)」を参照してください。 |
いいえ |
|
レスポンス・ヘッダーのみを戻し、実際のリソースは戻しません(つまり、メッセージ本文はありません)。これは、実際にダウンロードせずにリソースの特性を確認して、バンド幅を節約するのに役に立ちます。詳細は、Java EE 7 API仕様の
|
はい |
|
URIで識別された特定のリソースのリクエスト/レスポンス・チェーンで使用可能な通信オプションを戻します。
|
はい |
|
アノテーションの付けられたメソッドを使用してHTTPリクエストを処理する必要があることを示します。詳細は、Java EE 7 API仕様の |
該当なし |
次の項では、HTTPリクエストのJavaメソッドへのマッピングに使用されるJAX-RSアノテーションの詳細について説明します。
次の項に示す例は、Jersey 2.x (JAX-RS 2.0 RI)とともに提供されるブックマーク・サンプルからの抜粋です。ブックマーク・サンプルは、ユーザーやブラウザが設定したブックマークを保持するWebアプリケーションを提供します。
サンプル内のリソース・クラス、関連URIパス、各クラスにより実証されるHTTPメソッドについて、次の表にまとめます。
表2-3 Jerseyブックマーク・サンプルについて
リソース・クラス | URIパス | 実証されるHTTPメソッド |
---|---|---|
|
|
GET |
|
|
GET、PUT、DELETE |
|
|
GET、POST |
|
|
GET、PUT、DELETE |
ブックマーク・サンプルおよびその他のJerseyサンプルは、次のいずれかの方法でアクセスできます。
https://repo1.maven.org/maven2/org/glassfish/jersey/examples/bookmark/
にあるブックマーク・サンプルにアクセスする
GitHub (https://github.com/jersey/jersey/tree/master/examples/bookmark
)でブックマーク・サンプル・ソース・コードを参照する
https://repo1.maven.org/maven2/org/glassfish/jersey/bundles/jersey-examples/
で、各バージョンのWebLogic Server固有のサンプル・バンドルを含め、すべてのJerseyサンプルのMavenリポジトリを参照する
javax.ws.rs.GET
アノテーションは、URIにより識別されるリソースの表現をクライアントに送信します。レスポンスのエンティティ本文で戻される形式または表現は、HTML、プレーン・テキスト、JPEGなどです。詳細は、Java EE 7 API仕様の@GET
アノテーションを参照してください。
例2-5では、Jerseyブックマーク・サンプルのBookmarksResource
クラスからの、アノテーションが付けられたJavaメソッドgetBookmarkAsJsonArray
が、HTTP GETリクエストを処理します。Jerseyブックマーク・サンプルの詳細は、「Jerseyブックマーク・サンプルについて」を参照してください。
例2-5 HTTP GETリクエストのJavaメソッドへのマッピング(BookmarksResourceクラス)
import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.Path; ... public class BookmarksResource { ... @Path("{bmid: .+}") public BookmarkResource getBookmark(@PathParam("bmid") String bmid) { return new BookmarkResource(uriInfo, em, userResource.getUserEntity(), bmid); } @GET @Produces(MediaType.APPLICATION_JSON) public JSONArray getBookmarksAsJsonArray() { JSONArray uriArray = new JSONArray(); for (BookmarkEntity bookmarkEntity : getBookmarks()) { UriBuilder ub = uriInfo.getAbsolutePathBuilder(); URI bookmarkUri = ub. path(bookmarkEntity.getBookmarkEntityPK().getBmid()). build(); uriArray.put(bookmarkUri.toASCIIString()); } return uriArray; } ... }
例2-6では、Jerseyブックマーク・サンプルのBookmarkResource
クラスからの、アノテーションが付けられたJavaメソッドgetBookmark
が、HTTP GETリクエストを処理します。この例では、戻されたJSONオブジェクトの処理方法を示します。Jerseyブックマーク・サンプルの詳細は、「Jerseyブックマーク・サンプルについて」を参照してください。
例2-6 HTTP GETリクエストのJavaメソッドへのマッピング(BookmarkResourceクラス)
import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.Path; ... public class BookmarkResource { ... @GET @Produces(MediaType.APPLICATION_JSON) public JSONObject getBookmark() { return asJson(); } ... public JSONObject asJson() { try { return new JSONObject() .put("userid", bookmarkEntity.getBookmarkEntityPK().getUserid()) .put("sdesc", bookmarkEntity.getSdesc()) .put("ldesc", bookmarkEntity.getLdesc()) .put("uri", bookmarkEntity.getUri()); } catch (JSONException je){ return null; } } }
javax.ws.rs.PUT
アノテーションは、URIで識別された特定のリソースの表現を作成または更新します。詳細は、Java EE 7 API仕様の@PUT
アノテーションを参照してください。
例2-7では、Jerseyブックマーク・サンプルのBookmarkResource
クラスからの、アノテーションが付けられたJavaメソッドputBookmark
が、HTTP PUTリクエストを処理し、指定したブックマークを更新します。Jerseyブックマーク・サンプルの詳細は、「Jerseyブックマーク・サンプルについて」を参照してください。
例2-7 HTTP PUTリクエストのJavaメソッドへのマッピング
import javax.ws.rs.PUT; import javax.ws.rs.Produces; import javax.ws.rs.Path; ... public class BookmarkResource { ... @PUT @Consumes(MediaType.APPLICATION_JSON) public void putBookmark(JSONObject jsonEntity) throws JSONException { bookmarkEntity.setLdesc(jsonEntity.getString("ldesc")); bookmarkEntity.setSdesc(jsonEntity.getString("sdesc")); bookmarkEntity.setUpdated(new Date()); TransactionManager.manage(new Transactional(em) { public void transact() { em.merge(bookmarkEntity); }}); } }
javax.ws.rs.DELETE
アノテーションは、URIで識別された特定のリソースの表現を削除します。レスポンスのエンティティ本文ではステータス・メッセージが返されるか、または空の可能性があります。詳細は、Java EE 7 API仕様の@DELETE
アノテーションを参照してください。
例2-8では、Jerseyブックマーク・サンプルのBookmarkResource
クラスからの、アノテーションが付けられたJavaメソッドdeleteBookmark
が、HTTP DELETEリクエストを処理し、指定したブックマークを削除します。Jerseyブックマーク・サンプルの詳細は、「Jerseyブックマーク・サンプルについて」を参照してください。
例2-8 HTTP DELETEリクエストのJavaメソッドへのマッピング
import javax.ws.rs.DELETE; import javax.ws.rs.Produces; import javax.ws.rs.Path; ... public class BookmarkResource { ... @DELETE public void deleteBookmark() { TransactionManager.manage(new Transactional(em) { public void transact() { UserEntity userEntity = bookmarkEntity.getUserEntity(); userEntity.getBookmarkEntityCollection().remove(bookmarkEntity); em.merge(userEntity); em.remove(bookmarkEntity); }}); } }
javax.ws.rs.POST
アノテーションは、URIで識別された特定のリソースの表現でのアクションを作成、更新、または実行します。詳細は、Java EE 7 API仕様の@POST
アノテーションを参照してください。
例2-9では、Jerseyブックマーク・サンプルのBookmarksResource
クラスからの、アノテーションが付けられたJavaメソッドpostForm
が、HTTP POSTリクエストを処理し、指定した情報を更新します。Jerseyブックマーク・サンプルの詳細は、「Jerseyブックマーク・サンプルについて」を参照してください。
例2-9 HTTP POSTリクエストのJavaメソッドへのマッピング
import javax.ws.rs.POST; import javax.ws.rs.Produces; ... public class BookmarksResource { ... @POST @Consumes(MediaType.APPLICATION_JSON) public Response postForm(JSONObject bookmark) throws JSONException { final BookmarkEntity bookmarkEntity = new BookmarkEntity(getBookmarkId(bookmark.getString("uri")), userResource.getUserEntity().getUserid()); bookmarkEntity.setUri(bookmark.getString("uri")); bookmarkEntity.setUpdated(new Date()); bookmarkEntity.setSdesc(bookmark.getString("sdesc")); bookmarkEntity.setLdesc(bookmark.getString("ldesc")); userResource.getUserEntity().getBookmarkEntityCollection().add(bookmarkEntity); TransactionManager.manage(new Transactional(em) { public void transact() { em.merge(userResource.getUserEntity()); }}); URI bookmarkUri = uriInfo.getAbsolutePathBuilder(). path(bookmarkEntity.getBookmarkEntityPK().getBmid()). build(); return Response.created(bookmarkUri).build(); } }
リソースのクラス・レベルでjavax.ws.rs.Consumes
またはjavax.ws.rs.Produces
アノテーションを追加し、リクエストおよびレスポンス・メディア・タイプをカスタマイズします。次の項を参照してください。
javax.ws.rs.Consumes
アノテーションにより、クライアントから送信され、リソースが消費できる表現のMIMEメディア・タイプを指定できます。@Consumes
アノテーションはクラスとメソッド・レベルの両方に指定でき、複数のメディア・タイプを同じ@Consumes
宣言で宣言できます。
指定されたMIMEメディア・タイプを消費できるメソッドがリソース内にない場合、ランタイムはHTTP 「415 - サポートされていないメディア・タイプ」
エラーを返します。
詳細は、Java EE 7 API仕様の@Consumes
アノテーションを参照してください。
例2-11では、JavaクラスhelloWorld
に定義された@Consumes
アノテーションは、クラスがtext/plain
MIMEメディア・タイプを使用してメッセージを作成することを指定します。
例2-10 @Consumesを使用したリクエスト・メッセージのメディア・タイプのカスタマイズ
package samples.consumes; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/helloworld") public class helloWorld { ... @POST @Consumes("text/plain") public void postMessage(String message) { // Store the message } }
javax.ws.rs.Produces
アノテーションにより、リソースが生成でき、クライアントに戻すことができる、表現のMIMEメディア・タイプを指定できます。@Produces
アノテーションはクラスとメソッド・レベルの両方に指定でき、複数のメディア・タイプを同じ@Produces
宣言で宣言できます。
指定されたMIMEメディア・タイプを生成できるメソッドがリソース内にない場合、ランタイムはHTTP 「406 許可されません」
エラーを返します。
詳細は、Java EE 7 API仕様の@Produces
アノテーションを参照してください。
例2-11では、JavaクラスSomeResource
に指定された@Produces
アノテーションは、クラスがtext/plain
MIMEメディア・タイプを使用してメッセージを作成することを指定します。doGetAsPlainText
メソッドのデフォルトは、クラス・レベルで指定されたMIMEメディア・タイプです。doGetAsHtml
メソッドはクラス・レベルの設定をオーバーライドし、メソッドがプレーン・テキストではなくHTMLを生成することを指定します。
例2-11 @Producesを使用したレスポンスのメディア・タイプのカスタマイズ
package samples.produces; import javax.ws.rs.Produces; import javax.ws.rs.Path; @Path("/myResource") @Produces("text/plain") public class SomeResource { @GET public String doGetAsPlainText() { ... } @GET @Produces("text/html") public String doGetAsHtml() { ... } }
リソース・クラスが複数のMIMEメディア・タイプの生成が可能な場合、選択されたリソース・メソッドは、HTTPリクエストのAccept
ヘッダーに宣言された受入れ可能なメディア・タイプに対応します。例2-11では、Accept
ヘッダーがAccept: text/html
の場合、doGetAsPlainText
メソッドが呼び出されます。
複数のMIMEメディア・タイプが@Produces
アノテーションに含まれており、両方がクライアントに受入れ可能な場合、指定された最初のメディア・タイプが使用されます。例2-11では、Accept
ヘッダーがAccept: application/html, application/text
の場合、doGetAsHtml
メソッドが呼び出され、リストの最初に表示されるapplication/html
MIMEメディア・タイプが使用されます。
javax.ws.rs
パッケージにより、リクエスト・メッセージから情報を抽出してJavaメソッドのパラメータに注入できるアノテーションのセット(表2-4を参照)が定義されます。
表2-4 リクエスト・メッセージから情報を抽出するためのjavax.ws.rsアノテーション
アノテーション | 説明 |
---|---|
|
単一のBeanに集約済リクエスト・パラメータを注入します。詳細は、Java EE 7 API仕様の その他の使用方法の詳細は、Jersey 2.21ユーザー・ガイドのパラメータ・アノテーション(@*Param)に関する項を参照してください。 |
|
HTTP Cookie関連ヘッダーから情報を抽出し、メソッド・パラメータの値を初期化します。詳細は、Java EE 7 API仕様の |
|
次に示すアノテーションのいずれかを使用してバインドされるリクエスト・メタデータのデフォルト値を定義します。 |
|
|
|
タイプ |
|
HTTPヘッダーから情報を抽出し、メソッド・パラメータの値を初期化します。詳細は、Java EE 7 API仕様の |
|
URIパス・セグメントから情報を抽出し、メソッド・パラメータの値を初期化します。詳細は、Java EE 7 API仕様の |
|
相対URIを変数として定義します(URIパス・テンプレートとして参照)。詳細は、「リクエストURIからの変数情報の抽出方法(@PathParam)」を参照してください。 |
|
リクエストURIの問合せ部分から情報を抽出し、メソッド・パラメータの値を初期化します。詳細は、「リクエスト・パラメータの抽出方法(@QueryParam)」を参照してください。 |
javax.ws.rs.PathParam
アノテーションをリソースのメソッド・パラメータに追加し、リクエストURIから変数情報を抽出し、メソッド・パラメータの値を初期化します。@DefaultValue
アノテーションを使用して、変数値のデフォルト値を定義できます。「DefaultValueの定義方法(@DefaultValue)」を参照してください。
例2-3では、@PathParam
アノテーションが、@Path
アノテーションによりURIパスの一部として定義されたusername
変数の値をuserName
メソッド・パラメータに割り当てます。
例2-12 リクエストURIからの変数情報の抽出
package samples.helloworld; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.PathParam; // Specifies the path to the RESTful service @Path("/users") public class helloWorld { . . . @GET @Path("/{username}") @Produces("text/xml") public String getUser(@PathParam("username") String userName) { ... } }
javax.ws.rs.QueryParam
アノテーションをリソースのメソッド・パラメータに追加し、リクエストURIの問合せ部分から情報を抽出し、メソッド・パラメータの値を初期化します。
アノテーションの付けられたメソッド・パラメータの種類は次のとおりです。
プリミティブ型(int
、char
、byte
など)
ユーザー定義型
1つの文字列引数を受入れるコンストラクタ
1つの文字列引数を受入れる静的メソッドvalueOf
またはfromString
(たとえば、integer.valueOf(String)
)
List<T>
、Set<T>
、またはSortedSet<T>
@QueryParam
アノテーションが指定されても、関連する問合せパラメータがリクエストに存在しない場合、そのパラメータ値は、List
、Set
またはSortedSet
の場合は空のコレクション、プリミティブ型の場合はJava定義のデフォルト、およびその他のすべてのオブジェクト型の場合はNULLに設定されます。または、@DefaultValue
アノテーションを使用して、パラメータのデフォルト値を定義できます。「DefaultValueの定義方法(@DefaultValue)」を参照してください。
詳細は、Java EE 7 API仕様の@QueryParam
アノテーションを参照してください。
例2-13では、step
問合せパラメータがリクエストURIの問合せコンポーネントに存在する場合、その値はstep
メソッドのパラメータに整数値として割り当てられます。値が整数値として解析できない場合、400 (クライアント・エラー)
レスポンスが返ります。step
問合せパラメータがリクエストURIの問合せコンポーネント内に存在しない場合、値はNULLに設定されます。
javax.ws.rs.DefaultValue
アノテーションを追加して、次に示すアノテーションのいずれかを使用してバインドされるリクエスト・メタデータのデフォルト値を定義します。@CookieParam
、@FormParam
、@HeaderParam
、@MatrixParam
、@PathParam
または@QueryParam
。詳細は、Java EE 7 API仕様の@DefaultValue
アノテーションを参照してください。
例2-14では、step
問合せパラメータがリクエストURIの問合せコンポーネントに存在しない場合、デフォルト値2がstep
パラメータに割り当てられます。
クラスまたはメソッド・レベルでjavax.ws.rs.Encoded
アノテーションを追加して、@FormParam
、@MatrixParam
、@PathParam
または@QueryParam
のいずれかのアノテーションを使用してバインドされるパラメータ値のエンコードを有効にします。クラス・レベルで指定した場合は、そのクラスのすべてのメソッドのパラメータがエンコードされます。詳細は、Java EE 7 API仕様の@Encoded
アノテーションを参照してください。
例2-15の@Encoded
アノテーションは、@PathParam
アノテーションを使用してバインドされるパラメータ値のエンコードを有効にします。
例2-15 パラメータ値のエンコード
package samples.helloworld; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.PathParam; import javax.ws.rs.Encoded; // Specifies the path to the RESTful service @Path("/users") public class helloWorld { . . . @GET @Path("/{username}") @Produces("text/xml") @Encoded public String getUser(@PathParam("username") String userName) { ... } }
デフォルトでは、正常なGETリクエストには200 OK
、正常なPUTリクエストには201 CREATED
などの、HTTP仕様で定義されたデフォルト・レスポンス・コードを使用して、JAX-RSはHTTPリクエストに応答します。
場合によっては、返されたレスポンス・コードをカスタマイズする、または追加メタデータ情報をレスポンスに含めることがあります。たとえば、新しく作成されたリソースにURIを指定するためのLocation
ヘッダーを含めるような場合です。返されたレスポンス・メッセージは、javax.ws.rs.core.Response
クラスを使用して変更できます。
アプリケーションではResponse
クラスを直接拡張するか、表2-5
で定義された静的Responseメソッドの1つを使用することで、javax.ws.rs.core.Response.ResponseBuilder
インスタンスを作成してResponse
インスタンスを構築できます。詳細は、Java EE 7 API仕様のResponse
メソッドを参照してください。
表2-5 ResponseBuilderクラスを使用したレスポンス・インスタンスの作成
メソッド | 説明 |
---|---|
|
新しい |
|
新しい |
|
新しい |
|
新しい |
|
新しい |
|
新しい |
|
リダイレクトのための新しい |
|
新しい |
|
新しい |
|
一時的なリダイレクトのための新しい |
ResponseBuilder
インスタンスを作成した後は、表2-6で定義されたメソッドを呼び出してカスタム・リソースを定義できます。次に、build()
メソッドを呼び出して最終的なResponse
インスタンスを作成します。詳細は、Java EE 7 API仕様のResponse.ResponseBuilder
メソッドを参照してください。
表2-6 カスタム・レスポンスを構築するためのResponseBuilderメソッド
メソッド | 説明 |
---|---|
|
リソースに許可されているメソッドを設定します。 |
|
現在の |
|
キャッシュ・コントロールを設定します。 |
|
|
|
コンテンツの場所を設定します。 |
|
レスポンスにCookieを追加します。 |
|
メッセージ・エンティティのコンテンツ・エンコーディングを設定します。 |
|
エンティティを定義します。 |
|
有効期限を設定します。 |
|
レスポンスにヘッダーを追加します。 |
|
言語を設定します。 |
|
最終変更日を設定します。 |
|
リンク・ヘッダーを追加します。 |
|
1つ以上のリンク・ヘッダーを追加します。 |
|
場所を設定します。 |
|
新しい |
|
既存のヘッダーをすべて新しく指定したヘッダーで置き換えます。 |
|
ステータスを設定します。 |
|
エンティティ・タグを設定します。 |
|
レスポンス・メディア・タイプを設定します。 |
|
表現メタデータを設定します。 |
|
使用可能なバリアントの一覧を示す |
例2-16は、ResponseBuilder
を使用したResponse
インスタンスの構築方法を示しています。この例では、200 OK
の標準ステータス・コードが返され、レスポンスのメディア・タイプがtext/html
に設定されます。build()
メソッドの呼出しによって最終的なResponse
インスタンスが作成されます。
例2-16 カスタム・レスポンスの構築
import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; import javax.ws.rs.core.ResponseBuilder; ... @Path("/content") public class getDocs { @GET @Path("{id}") public Response getHTMLDoc(@PathParm("id") int docId) { Document document = ...; ResponseBuilder response = Response.ok(document); response.type("text/html"); return response.build(); } }
汎用型を使用してHTTPレスポンスを構築する場合、実行時に型のイレイジャを回避するために、汎用型を保持するjavax.ws.rs.core.GenericEntity
オブジェクトを作成する必要があります。詳細は、Java EE 7 API仕様のGenericEntity
メソッドを参照してください。
例2-17に、汎用型を保持するGenericEntity
を使用する、HTTPレスポンスの構築方法の例を示します。
例2-17 汎用型を使用したカスタム・レスポンスの構築
import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; import javax.ws.rs.core.ResponseBuilder; javax.ws.rs.core.GenericEntity; ... @Path("/content") public class getDocs { @GET @Path("{id}") public Response getHTMLDoc(@PathParm("id") int docId) { Document document = ...; List<String> list = new ArrayList<String>(); GenericEntity<List<String>> entity = new GenericEntity<List<String>>(list) {}; ... ResponseBuilder response = Response.ok(document); response.entity(entity); return response.build(); } }
表2-7に、HTTPリクエストおよびレスポンスのエンティティ本文で自動的にサポートされるJavaタイプを示します。
表2-7 HTTPリクエストおよびレスポンスのエンティティ本文でサポートされるJavaタイプ
Javaタイプ | サポートされるメディア・タイプ |
---|---|
|
すべてのメディア・タイプ(*/*) |
|
すべてのメディア・タイプ(*/*) |
|
すべてのメディア・タイプ(*/*) |
|
すべてのメディア・タイプ(*/*) |
|
すべてのメディア・タイプ(*/*) |
|
すべてのメディア・タイプ(*/*) |
|
XMLメディア・タイプ( |
|
XMLメディア・タイプ( |
|
フォーム・コンテンツ( |
|
すべてのメディア・タイプ(*/*)、 |
RESTful Webサービスで、表2-7に示されていないタイプを使用する場合は、表2-8に定義されているインタフェースのいずれかを実装することでエンティティ・プロバイダを定義し、HTTPリクエストおよびレスポンスのエンティティ本文をメソッドのパラメータおよび戻りタイプにマップする必要があります。
表2-8 HTTPリクエストおよびレスポンスのエンティティ本文をメソッドのパラメータおよび戻りタイプにマップするためのエンティティ・プロバイダ
エンティティ・プロバイダ | 説明 |
---|---|
|
HTTPリクエストのエンティティ本文をメソッドのパラメータにマップします。 以下に例を示します。 @Consumes("application/x-www-form-urlencoded") @Provider public class FormReader implements MessageBodyReader<NameValuePair> { ... } |
|
HTTPレスポンスのエンティティ本文に戻り値をマップします。 以下に例を示します。 @Produces("text/html") @Provider public class FormWriter implements MessageBodyWriter<Hashtable<String, String>> { ... } |
注意: Jersey JSONには、Jersey JSON拡張モジュールとともに配布されるJAX-RSMessageBodyReader プロバイダおよびMessageBodyWriter プロバイダのセットが用意されています。詳細は、Jersey 2.21ユーザー・ガイドのJSONに関する項を参照してください。 |
次に示すコードの抜粋は、カスタム・タイプを返すメソッド(getClass
)を含むクラスの例を示しています。このコードにはエンティティ・プロバイダを記述する必要があります。
public class Class1 { public String hello() { return "Hello"; } public Class2 getClass(String name) { return new Class2(); }; } public class Class2 { public Class2() { } }
javax.ws.rs.core.Context
アノテーションを使用すると、アプリケーション・デプロイメント・コンテキストと個別リクエストのコンテキストに関する情報にアクセスできます。表2-9に@Context
アノテーションを使用してアクセスできるコンテキスト・タイプの概要を示します。詳細は、Java EE 7 API仕様の@Context
アノテーションを参照してください。
表2-9 コンテキスト・タイプ
コンテキスト・タイプ名 | 目的 |
---|---|
|
HTTPヘッダー情報にアクセスします。 |
|
一連の検索基準を基に、プロバイダ・インスタンスを参照します。 |
|
最も一致する表現バリアントを判別し、リソースの現在の状態が定義済の前条件に一致するかどうかを評価します。詳細は、「条件付きGETの使用」を参照してください。 |
|
セキュリティ・コンテキストにアクセスし、RESTful Webサービスを保護します。詳細は、「SecurityContextを使用したRESTful Webサービスの保護」を参照してください。 |
|
アプリケーションおよびリクエストURI情報にアクセスします。詳細は、「URIの構築」を参照してください。 |
javax.ws.rs.core.UriInfo
を使用して、アプリケーションおよびリクエストURI情報にアクセスできます。具体的には、UriInfo
は次の情報を返すために使用できます。
デプロイされたアプリケーションの基底URI
基底URIに相対するリクエストURI
絶対パスURI (問合せパラメータ付きの場合もあり)
UriInfo
を使用して、URIまたはjavax.ws.rs.core.UriBuilder
インスタンスを返すことができます。UriBuilder
はURIの構築プロセスを簡素化し、新規URIの構築、または既存URIの拡張にも使用できます。
UriBuilder
メソッドは、対応するURIコンポーネントでは許可されていない文字のコンテキスト・エンコーディングを、次のルールに基づいて実行します。
問合せパラメータについてはapplication/x-www-form-urlencoded
メディア・タイプ(URL: http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
にあるHTML仕様の「Forms」で定義)
その他すべてのコンポーネントについてはRFC 3986 (URL: http://www.ietf.org/rfc/rfc3986.txt
で定義)
例2-18に、@Context
を使用したUriInfo
のインスタンスの取得と、そのインスタンスを使用して、リクエストURIの絶対パスをUriBuilder
インスタンスとして返す方法を示します。次に、UriBuilder
を使用して、ユーザーIDをパス・セグメントとして追加して特定のユーザー・リソースに対するURIを構築し、配列内に格納します。この例では、UriInfo
インスタンスはクラス・フィールドに注入されます。この例は、「Jerseyブックマーク・サンプルについて」に記述されているとおり、ブックマーク・サンプルからの抜粋です。
例2-18 URIの構築
import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.Context; ... @Path("/users/") public class UsersResource { @Context UriInfo uriInfo; ... @Produces("application/json") public JSONArray getUsersAsJsonArray() { JSONArray uriArray = new JSONArray(); for (UserEntity userEntity : getUsers()) { UriBuilder ub = uriInfo.getAbsolutePathBuilder(); URI userUri = ub .path(userEntity.getUserid()) .build(); uriArray.put(userUri.toASCIIString()); } return uriArray; } }
条件付きGETを使用すると、GETリクエストを処理する前に前条件を1つ以上評価できます。前条件が一致する場合、Not Modified (304)
レスポンスを通常のレスポンスのかわりに返すことが可能で、これによって潜在的に帯域幅が縮小され、サーバー・パフォーマンスが向上します。
JAX-RSは、条件付きGETの実行を可能にするjavax.ws.rs.core.Request
コンテキスト・インタフェースを提供します。evaluatePreconditions()
メソッドを呼び出してjavax.ws.rs.core.EntityTag
、(java.util.Date
オブジェクトとして)最終変更日のタイムスタンプ、あるいはその両方を渡します。値はIf-None-Match
ヘッダーまたはIf-Not-Modified
ヘッダーと、このヘッダーがリクエストとともに送信された場合は、それぞれ比較されます。
ヘッダーがリクエストとともに含まれ、前条件値がヘッダー値と一致する場合は、evaluatePreconditions()
メソッドが定義済のResponseBuilder
レスポンスをNot Modified (304)
のステータス・コードとともに返します。前条件値が一致しない場合、evaluatePreconditions()
メソッドはNULLを返し、通常のレスポンスが200, OK
ステータスとともに返されます。
例2-19に、EntityTag
をevaluatePreconditions()
メソッドに渡し、前条件の一致の有無に基づいてレスポンスを構築する方法を示します。
例2-19 条件付きGETの使用
... @Path("/employee/{joiningdate}") public class Employee { Date joiningdate; public Employee(@PathParam("joiningdate") Date joiningdate, @Context Request req, @Context UriInfo ui) { this.joiningdate = joiningdate; ... this.tag = computeEntityTag(ui.getRequestUri()); if (req.getMethod().equals("GET")) { Response.ResponseBuilder rb = req.evaluatePreconditions(tag); // Preconditions met if (rb != null) { return rb.build(); } // Preconditions not met rb = Response.ok(); rb.tag(tag); return rb.build(); } } }
Web Application Description Language (WADL)は、RESTful Webサービス・アプリケーションを記述するXMLベースのファイル形式です。デフォルトでは、ベースWADLが実行時に生成され、RESTfulアプリケーションの基底URIでGET
を/application.wadl
リソースに発行することで、RESTful Webサービスからアクセスできます。
注意: コンテキスト・タイプapplication/vnd.sun.wadl+xml は、Microsoft Internet Explorer 8では認識されません。その場合、参照用にWADLのコピーをローカル・ファイル・システムにダウンロードできます。 |
以下に例を示します。
GET http://<path_to_REST_app>/application.wadl
もしくは、OPTIONS
メソッドを使用して特定のリソースに対するWADLを返すこともできます。
例2-20に、例2-1の簡単なRESTful Webサービスに対するWADLの例を示します。
例2-20 WADLの例
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <application xmlns="http://research.sun.com/wadl/2006/10"> <doc xmlns:jersey="http://jersey.dev.java.net/" jersey:generatedBy="Jersey: 0.10-ea-SNAPSHOT 08/27/2008 08:24 PM"/> <resources base="http://localhost:9998/"> <resource path="/helloworld"> <method name="GET" id="sayHello"> <response> <representation mediaType="text/plain"/> </response> </method> </resource> </resources> </application>
JAX-RSとEJBテクノロジおよびContexts and Dependency Injection (CDI)との統合やJAXBおよびJSONの使用など、高度なRESTful Webサービス開発タスクの詳細は、Jersey 2.21ユーザー・ガイドを参照してください。