REST (REpresentational State Transfer) スタイルのアーキテクチャーでは、リソースの表現を転送するためにリクエストとレスポンスが作成されます。リソースはグローバル ID によって識別され、この ID には通常、URI (Uniform Resource Identifier) が使われます。クライアント・アプリケーションは、HTTP メソッド (GET、POST、PUT、DELETE など) を使ってリソースまたはリソースの集合を操作します。一般的に、GET メソッドはリソースまたはリソースの集合を取得または一覧表示するために使われ、POST はリソースの作成に、PUT はリソースの更新または置換に、DELETE はリソースの削除に使われます。
例えば GET http://host/context/employees/12345 を実行した場合には、ID が 12345 の従業員の表現が取得されます。レスポンスの表現は、その従業員の詳細情報を含む XML または ATOM の場合もあり、より適切な UI を提供するための JSP/HTML ページの場合もあります。どちらの表現が表示されるかは、サーバー・サイドの実装と、クライアントが要求する MIME タイプに依存します。
RESTful な Web サービスというのは、REST の原則と HTTP を使用して実装される Web サービスです。一般的に、RESTful な Web サービスでは、ベースとなるリソースの URI、そのサービスでサポートされる表現やレスポンスの MIME タイプ、そのサービスでサポートされる操作を定義します。
この記事では、Java によるサーバー・サイドの RESTful な Web サービスを、Spring を使用して作成する方法を学びます。この記事の例で使用するものは、ブラウザー、curl、そしてリクエストを行うクライアントのための、RESTClient というFirefox プラグインです。この記事で使われているソース・コードはダウンロードすることができます。
この記事では、読者が REST の基本を理解しているものとします。REST に関する詳細については「参考文献」を参照してください。
Spring フレームワークで REST がサポートされる以前は、他のいくつかの実装 (Restlet、RestEasy、Jersey など) を使って Java の世界における RESTful な Web サービスを作成していました。それらの中で最も重要なものである Jersey は、JAX-RS (JSR 311) のリファレンス実装です。JSR 311 と Jersey について詳しくは「参考文献」を参照してください。
Java EE フレームワークとして広く使われている Spring では、RESTful な Web サービスを作成するためのサポートがリリース 3 で追加されました。Spring 3 での REST サポートは JAX-RS の実装ではありませんが、JAX-RS の仕様で定義されている以上の機能を持っています。この REST サポートは Spring の MVC レイヤーにシームレスに統合されており、Spring を使って作成されるアプリケーションの中に容易に取り入れることができます。
Spring での REST サポートの主な機能には、以下のようなものがあります。
- アノテーション (
@RequestMappingや@PathVariableなど) により、リソースの特定や URI マッピングをサポートすることができます。 ContentNegotiatingViewResolverにより、多様な MIME タイプやコンテンツ・タイプの多様な表現をサポートすることができます。- 元の MVC レイヤーにシームレスに統合されており、従来と同様のプログラミング・モデルを使用することができます。
このセクションの例では、Spring 3 環境のセットアップと、Tomcat に統合可能な「Hello world」アプリケーションの作成について、順を追って説明します。次に、もっと複雑なアプリケーションを使用して、複数の MIME タイプの表現のサポートや JAXB のサポートなど、Spring 3 による REST サポートの最重要事項を紹介します。そうした概念の説明では、理解の助けとなるようにコード・スニペットを記載します。この記事のサンプル・コードはすべてダウンロードすることができます。
Hello World: Spring 3 の REST サポートを使う
この例の手順を追えるように開発環境をセットアップするためには、以下のものが必要です。
- IDE: Eclipse IDE for JEE (v3.4 またはそれ以降のバージョン)
- Java SE5 またはそれ以降のバージョン
- Web コンテナー: Apache Tomcat 6.0 (Jetty やその他のものでも構いません)
- Spring 3 フレームワーク (この記事の執筆時点では v3.0.3 が最新です)
- その他のライブラリー: JAXB 2、JSTL、commons-logging
Eclipse で動的な Web アプリケーションを作成し、そのランタイムとして Tomcat 6 を設定します。次に web.xml ファイルの内容を適切なものにし、Spring の WebApplicationContext を有効にします。この例では、Spring Bean の構成を 2 つのファイルに分散しており、rest-servlet.xml は MVC/REST 関連の構成を処理し、rest-context.xml はサービス・レベルの構成 (データ・ソース Bean など) を処理します。リスト 1 は web.xml のうち、Spring を構成する部分のスニペットです。
リスト 1. web.xml で Spring の WebApplicationContext を有効にする
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/rest-context.xml
</param-value>
</context-param>
<!-- This listener will load other application context file in addition to
rest-servlet.xml -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
|
rest-servlet.xml ファイルの中で、MVC に関連する Spring の構成 (コントローラー、ビュー、ビュー・リゾルバー) を設定します。リスト 2 に最も重要なスニペットを示します。
リスト 2. rest-servlet.xml の中で Spring の MVC 構成を設定する
<context:component-scan base-package="dw.spring3.rest.controller" /> <!--To enable @RequestMapping process on type level and method level--> <bean class="org.springframework.web.servlet.mvc.annotation .DefaultAnnotationHandlerMapping" /> <bean class="org.springframework.web.servlet.mvc.annotation .AnnotationMethodHandlerAdapter" /> <!--Use JAXB OXM marshaller to marshall/unmarshall following class--> <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>dw.spring3.rest.bean.Employee</value> <value>dw.spring3.rest.bean.EmployeeList</value> </list> </property> </bean> <bean id="employees" class= "org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg ref="jaxbMarshaller" /> </bean> <bean id="viewResolver" class= "org.springframework.web.servlet.view.BeanNameViewResolver" /> |
以下は上記コードの各部分の説明です。
-
component-scan - Spring のアノテーションを持つクラスに対する自動スキャンを有効にします。
実際には、component-scan はコントローラー・クラスで定義された@Controllerアノテーションを検出するために使われます。 DefaultAnnotationHanlderMappingとAnnotationMethodHandlerAdapter- クラスやメソッドの
@ReqeustMappingアノテーションを Spring で処理させるための Bean です。
このアノテーションについては次のセクションで詳しく説明します。 Jaxb2Mashaller- JAXB 2 を使って OXM (Object XML Mapping) を行うマーシャラーとアンマーシャラーを定義します。
MashallingView- Jaxb2Mashaller を利用する XML 表現のビューを定義します。
BeanNameViewResolver- ユーザーが指定する Bean の名前を使ってビュー・リゾルバーを定義します。
この例では「employees」という名前のMarshallingViewを使います。
これで Spring 関係の構成は終わりです。次のステップでは、ユーザー・リクエストを処理するコントローラーを作成します。リスト 3 はコントローラー・クラスを示しています。
リスト 3. dw.spring3.rest.controller パッケージの EmployeeController
@Controller
public class EmployeeController {
@RequestMapping(method=RequestMethod.GET, value="/employee/{id}")
public ModelAndView getEmployee(@PathVariable String id) {
Employee e = employeeDS.get(Long.parseLong(id));
return new ModelAndView(XML_VIEW_NAME, "object", e);
}
}
|
@RequestMapping アノテーションは Spring の REST 機能にとっての鍵です。@RequestMapping アノテーションは、アノテーションが付けられたメソッドによって、どの HTTP メソッド (RequestMethod.GET) と、どの URI (/employee/{id}) を処理するのかを指定します。以下の点に注意してください。
{id}というプレースホルダーの場合、{} の中の値は@PathVariableアノテーションを使ってメソッド・パラメーターの中に注入されます。- XML_VIEW_NAME は
employeesです。これは rest-servlet.xml の中で定義されたビューの名前です。 employeeDSは単純なメモリー・ベースのデータ・ソースですが、この実装についてはこの記事では説明しません。
この Web アプリケーションを Tomcat に公開します。この時点でブラウザーを開き、URL として http://<host>:<port>/<appcontext>/service/employee/1 を入力します。ブラウザーには、ID が 1 の従業員の XML ビューが表示されるはずです。
先に進み、Spring の REST サポートに関する機能についてさらに学びましょう。
リソースの操作には、GET、POST、PUT、DELETE などの HTTP メソッドを使います。先ほど、GET メソッドを使って従業員情報を取得する方法を学びました。今度は POST、PUT、DELETE について学びます。
@RequestMapping アノテーションの機能を使うと、さまざまなメソッドを処理するコードは非常に似たものになります。リスト 4 は EmployeeController クラスのコード・スニペットを示しています。
リスト 4. dw.spring3.rest.controller の EmployeeController
@RequestMapping(method=RequestMethod.POST, value="/employee")
public ModelAndView addEmployee(@RequestBody String body) {
Source source = new StreamSource(new StringReader(body));
Employee e = (Employee) jaxb2Mashaller.unmarshal(source);
employeeDS.add(e);
return new ModelAndView(XML_VIEW_NAME, "object", e);
}
@RequestMapping(method=RequestMethod.PUT, value="/employee/{id}")
public ModelAndView updateEmployee(@RequestBody String body) {
Source source = new StreamSource(new StringReader(body));
Employee e = (Employee) jaxb2Mashaller.unmarshal(source);
employeeDS.update(e);
return new ModelAndView(XML_VIEW_NAME, "object", e);
}
@RequestMapping(method=RequestMethod.DELETE, value="/employee/{id}")
public ModelAndView removeEmployee(@PathVariable String id) {
employeeDS.remove(Long.parseLong(id));
List<Employee> employees = employeeDS.getAll();
EmployeeList list = new EmployeeList(employees);
return new ModelAndView(XML_VIEW_NAME, "employees", list);
}
|
以下は上記コードの各部分の説明です。
RequestMethod.<HTTP メソッド>の値は、アノテーションが付けられたメソッドによって、どの HTTP メソッドを処理するのかを指定します。@RequestBodyによって、HTTP リクエストの本体の内容がパラメーターとして注入されます。この例では、HTTP リクエストの本体は従業員を表現する XML データです。ここでは JAXB 2 を使って XML を Java Bean にアンマーシャリングし、その Bean を永続化します。リクエストの本体のサンプルは以下のようなものです。
<employee><id>3</id><name>guest</name></employee>
- メソッド・パラメーターに注入可能な他の有用なアノテーションには、
@PathVariable、@RequestParmなどがあります。Spring のドキュメントにはアノテーションの完全なリストがあります (「参考文献」を参照)。
通常はリソースの集合も操作する必要があります。例えば、単に 1 人の情報だけではなく、すべての従業員の情報を取得する必要があるかもしれません。この実装方法は先ほどのケースと同様です。必要なことは URI を /employee から /employees に変更することだけです。employee を複数形にすることで、集合というセマンティクスが見事に表現されます。リスト 5 はその実装方法を示しています。
リスト 5. EmployeeController の getAllEmployees
@RequestMapping(method=RequestMethod.GET, value="/employees")
public ModelAndView getEmployees() {
List<Employee> employees = employeeDS.getAll();
EmployeeList list = new EmployeeList(employees);
return new ModelAndView(XML_VIEW_NAME, "employees", list);
}
|
Employee 集合のラッパー・クラスを宣言する必要があります。このラッパー・クラスは JAXB 2 にとって必要なクラスです。JAXB 2 はラッパー・クラスがないと java.util.List クラスを適切にマーシャリングすることができないからです。リスト 6 は EmployeeList クラスを示しています。
リスト 6. dw.spring3.rest.bean の EmployeeList クラス
@XmlRootElement(name="employees")
public class EmployeeList {
private int count;
private List<Employee> employees;
public EmployeeList() {}
public EmployeeList(List<Employee> employees) {
this.employees = employees;
this.count = employees.size();
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@XmlElement(name="employee")
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
|
REST サービスのもう 1 つの共通機能として、REST サービスでは、リクエストに従ってさまざまな表現を生成することができます。例えば、クライアントが全従業員の HTML 表現またはテキスト表現を要求した場合、サーバーはユーザーに対して整形式の HTML ページを生成する必要があります。クライアントが従業員のアプリケーション表現または XML 表現を要求した場合、サーバーは XML による結果を生成する必要があります。その他、よく使われる表現形式には ATOM や PDF があります。
Spring 3 には、ContentNegotiatingViewResolver という新しいビュー・リゾルバーが導入されています。このリゾルバーは、リクエストのコンテンツ・タイプ (リクエスト・ヘッダーの Accept プロパティー) または URI 接尾辞に従ってビュー・リゾルバーを切り替えることができます。下記の例では ContentNegotiatingViewResolver を使って複数の表現のサポートを実装しています。
rest-servlet.xml ファイルの中で、元々定義されている viewResolver をコメントアウトし、代わりに ContentNegotiatingViewResolver を使用します (リスト 7)。
リスト 7. コンテンツ・ネゴシエーションを定義する
<bean class="org.springframework.web.servlet.view .ContentNegotiatingViewResolver"> <property name="mediaTypes"> <map> <entry key="xml" value="application/xml"/> <entry key="html" value="text/html"/> </map> </property> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view .BeanNameViewResolver"/> <bean class="org.springframework.web.servlet.view .UrlBasedViewResolver"> <property name="viewClass" value= "org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </list> </property> </bean> |
この定義は、リクエストのコンテンツ・タイプとして application/xml と text/html の 2 つを処理できることを示しています。またこのコードは 2 つのビュー・リゾルバーを定義しており、BeanNameViewResolver は application/xml を処理し、UrlBasedViewResolver は text/html を処理します。
実際には、ブラウザーに http://<host>:<port>/<appcontext>/service/employees が入力されると、ブラウザーは従業員の text/html 表現を要求します。すると UrlBasedViewResolver が有効になり、Spring はビューとして /WEB-INF/jsp/employees.jsp を選択します。リクエスト・ヘッダーに Accept:application/xml を追加してリクエストを呼び出すと、BeanNameViewResolver が有効になります。リスト 5 のコードの場合、employees という名前のビューを使って表現しますが、これは先ほど定義された JAXB 2 マーシャラーのビューです。
getAllEmployees() のコントローラー・コードは変わりません。employees.jsp ページは employees という名前のモデル・オブジェクトを使ってページのレンダリングを行います。リスト 8 は employees.jsp のコード・スニペットです。
リスト 8. /WEB-INF/jsp の employees.jsp
<table border=1>
<thead><tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr></thead>
<c:forEach var="employee" items="${employees.employees}">
<tr>
<td>${employee.id}</td>
<td>${employee.name}</td>
<td>${employee.email}</td>
</tr>
</c:forEach>
</table>
|
ここまでの段階で作成したものは、従業員に対する CRUD (Create、Read、Update、Delete) 操作をサポートする単純で RESTful な Web サービスでした。このセクションでは、このサービスと通信する方法について説明します。ここでは curl を使って REST サービスをテストします。
RESTClient という Firefox プラグインを使って REST サービスをテストすることもできます。RESTClient には使いやすくて優れた UI があります。ダウンロードについては「参考文献」を参照してください。
curl は、HTTP/HTTPS プロトコルを使ってサーバーにリクエストを送信するためによく使われるコマンドライン・ツールです。curl は任意の HTTP メソッドを使ってコンテンツを送信できるため、RESTful な Web サービスと通信する上で便利なツールです。curl は Linux® と Mac® にユーティリティーとして組み込まれています。Windows® プラットフォームの場合には、curl をダウンロードすることができます (「参考文献」を参照)。
全従業員の情報が取得されるように、最初の curl コマンドを初期化するためには、以下の内容を入力します。
curl –HAccept:application/xml http://localhost:8080/rest/service/employees |
このコマンドに対するレスポンスは XML であり、全従業員の情報が含まれています (図 1)。
図 1. 全従業員の情報の XML 表現
また、上述の URL にブラウザーでアクセスすることもできます。その場合には、Accept ヘッダーで text/html が指定されるため、employees.jsp で定義された表が表示されます。図 2 はその例を示しています。
図 2. 全従業員の情報の HTML 表現
新しい従業員の情報をサーバーに POST するためには、下記のコードを使用します。リスト 4 の addEmployee() コードはリクエストの本体を使って新しい従業員の情報を Employee オブジェクトにアンマーシャリングしています。
curl -X POST -HContent-type:application/xml --data "<employee><id>3</id><name>guest</name><email>guest@ibm.com</employee>" http://localhost:8080/rest/service/employee |
これにより、新しい従業員の情報が追加されます。最初の例を使用して従業員リストを検証することができます。
PUT メソッドは POST メソッドと同様です。
curl -X PUT -HContent-type:application/xml --data "<employee><id>3</id><name>guest3</name><email>guest3@ibm.com</employee>" http://localhost:8080/rest/service/employee/3 |
上記のコードは ID が 3 の従業員のデータを更新します。
Spring 3 は MVC レイヤーで REST をサポートするようになったため、Spring の API とアノテーションを使って RESTful な Web サービスを作成することができます。この記事では、例を使って Spring 3 の新機能の使い方をいくつか説明しました。これらの例と説明から、Java によるサーバー・サイドの RESTful な Web サービスを容易に作成できるはずです。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Article source code | src.zip | 9KB | HTTP |
学ぶために
- REST の紹介、その他関連のリンクをウィキペディアで見てください。
- Spring 3 のすべてを学んでください。
- Jersey のホームページには、ダウンロード・ファイル、サンプル・コードのアーカイブ、ユーザー・ガイド、JAX-RS の API のドキュメントなどが用意されています。Jersey は、(CDDL と GPL という 2 つのライセンスに従う) オープンソースで本番品質の JAX-RS (JSR 311) リファレンス実装であり、RESTful な Web サービスの構築に使用することができます。
- 「Jersey と Apache Tomcat を使って RESTful な Web サービスを作成する」(developerWorks、2009年9月) は、この記事と同じ著者による記事です。この記事では、Jersey を Apache Tomcat に統合することで、サーブレット・スタイルのサービスを RESTful なサービスにスムーズに変換する方法を解説しています。
- JAXB リファレンス実装プロジェクトに関する資料を読んでください。
製品や技術を入手するために
- Spring 3 をダウンロードし、またドキュメントやチュートリアルを入手してください。
- Windows 用の curl を入手してください。
- Firefox の RESTClient 拡張機能を入手してください。この拡張機能を利用することで、RESTful/WebDav サービスを利用したりテストしたりすることができます。
- IBM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版で、DB2®、Lotus®、Rational®、Tivoli®、WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。
議論するために
- developerWorks blogs から developerWorks のコミュニティーに加わってください。
- 今すぐ My developerWorks プロフィールを作成し、REST、Web サービス、Spring に関するウォッチ・リストを設定してください。My developerWorks とずっとつながっていられます。
- Web 開発に関心を持つ他の developerWorks メンバーを見つけてください。
- Web 開発者の方は、その経験や知識を Web 開発グループの他の人達と共有してください。
- Web の話題に焦点を絞った developerWorks のグループの 1 つに参加し、皆さんの知識を共有してください。
- Roland Barcia が彼のブログの中で Web 2.0 とミドルウェアについて語っています。
- developerWorks のメンバーが Web のトピックに関して共有するブックマークを調べてみてください。
- 即座に答えを得るために、Web 2.0 Apps フォーラムを訪れてください。

