いまさら聞けないRESTの基礎知識、JAX-RSを使ったREST APIの作り方と使い方:3つのフレームワークで学ぶエンタープライズJava開発入門(3)(2/3 ページ)
新規のエンタープライズJava開発において現在有力視される3つのフレームの違いについて解説する連載。前回から複数回に分けて、MVCのViewとControllerにフォーカスして各要素を紹介しています。今回はJava EEのJAX-RSについて。JAX-RSの基本的な設計方針であるRESTについて解説し、Struts 1、JSFとの違いやJAX-RSの使いどころを紹介します。
JAX-RSによるCRUD操作のWebアプリケーション開発
リソースクラスの作成
それでは、従業員データを対象としたCRUD操作を提供するリソースクラスを作ってみましょう。このリソースクラスは、以下のように、IDと名前、年齢を持ちます。
public class Employee { private long id; private String name; private int age; // コンストラクタ、アクセッサは省略 }
従業員データを操作するためのURIとHTTPメソッドは以下のように定義します。
従業員の操作 | メソッド | URI | レスポンスの表現形式 |
---|---|---|---|
検索 | GET | /crudsample/employees?name={name} | JSON、XML |
取得 | GET | /crudsample/employees/{ID} | JSON、XML |
登録 | POST | /crudsample/employees | JSON、XML |
更新 | PUT | /crudsample/employees/{ID} | なし |
削除 | DELETE | /crudsample/employees/{ID} | なし |
このようにRESTでは、操作内容とHTTPメソッドを一致させます。上記の取得・更新・削除のように、同一のURIでもHTTPメソッドを変えることによって異なる操作を設定できます。
リソースに対応するクラスの作成
JAX-RSで上記のリソースに対応するEmployeeResourceクラスを作成します。少々長くなりますので、ソースコードを分割しながら紹介します(リスト2-1〜3)。
まずはクラス宣言とフィールド宣言です。
@Path("crudsample/employees") //【1】このリソースの起点のURIを指定 @RequestScoped //【2】CDIと統合 public class EmployeeResource { //【3】ビジネスロジックを注入 @Inject private EmployeeService service;
ポイントを解説します。
【1】では、@Pathアノテーションによりリソース全体で共通のURIを定義しています。前述の表では、「/crudsample/employees」というURIがどの操作でも共通になっています。そのようなURIはリソースクラスの@Pathアノテーションに設定することで、一元化して定義できます。
【2】では、リソースクラスをCDIのBeanとして宣言しています。Java EE環境では、JAX-RSとCDIを統合できるため、インジェクションが可能となります。
【3】ではビジネスロジックを実行するEmployeeServiceというBeanをインジェクションしています。【2】でリソースクラスをCDIのBeanとしたことにより、他のCDI Beanをインジェクションできます。
続いて、HTTPメソッドのGETに対応するリソースクラスのメソッドを説明します。まずは、名前を指定して従業員を検索するsearchメソッドです。このメソッドは次のURIに対応付けています。
GET /curdsample/employees?name=hoge HTTP/1.1
@GET // 【4】GET crudsample/employees?name=<name> に対応 @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) //【5】XMLかJSONを生成 public List<Employee> search(@QueryParam("name") String name) { return service.findByName(name); }
【4】では、@GETアノテーションを指定してsearchメソッドを上記のGETリクエストに対応付けています。URIに含まれるクエリストリングnameの値(上のURIの例ではhoge)は、searchメソッドの引数nameに割り当てられます。これは引数に、@QueryStringアノテーションを指定しているためです。JAX-RSではHTTPリクエストのさまざまな値を取得するためのアノテーションを多数用意しています。
【5】では、@Producesアノテーションにより、searchメソッドの戻り値のList
実行時にどちらのデータ形式を選択するかは、クライアントからの指定に従います。クライアントのHTTPリクエストに、受け入れ可能な表現形式を示すAcceptヘッダがある場合、その形式で返却します。
例えば、「Accept : application/json」ヘッダを付与して実行すると、以下のようなJSON形式のデータを返却します。
一方、「Accept: Application/xml」ヘッダを付与して、リクエストを発行すると、以下のようなXML形式のデータを返却します。
上記以外のAcceptヘッダを指定すると、エラーとなります。
このように、アノテーションの設定のみでさまざまな表現形式に対応できるのがJAX-RSの特徴の1つです。
次に、従業員をIDで検索するメソッドを見てみましょう。
@GET @Path("{id}") // 【6】crudsample/employees/{id} に対応 @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Employee get(@PathParam("id") long id) { return service.findById(id); }
【6】では 従業員1人分の情報を取得するためのGETリクエストのURIを定義しています。getメソッドに設定した「@Path(“{id}”)」というアノテーションは、リソースクラスに付与した@Pathアノテーションからの相対パスとして解釈されるため、「/crudsample/employees /{id}」というURIに対応します。
{id}のような{ }で囲まれた文字列は、URIの中の可変文字列を意味しています。IDを指定するようなリソースに対しては、URI中にIDを埋め込む方式がRESTでは一般的です。
URIの可変文字列をメソッドの中で使用するには、メソッドの引数に@PathParamアノテーションを指定します。
最後は、HTTPメソッドのPOST、PUT、DELETEに対応するメソッドです。
@POST // 【7】POST crudsample/employees に対応 @Consumes(MediaType.APPLICATION_FORM_URLENCODED) //【8】HTTPフォームを受け取る @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Employee newEmployee(@FormParam("name")String name, @FormParam("age")int age) { return service.save(name, age); } @PUT // 【9】PUT curdsample/employees/{id} に対応 @Path("{id}") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public void updateEmployee(@PathParam("id") long id, @FormParam("name")String name, @FormParam("age")int age) { service.update(new Employee(id, name, age)); } @DELETE // 【10】DELETE crudsample/employees/{id} に対応 @Path("{id}") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public void deleteEmployee(@PathParam("id") long id) { service.delete(id); } }
【7】では、@POSTアノテーションを指定して、POSTに対応するメソッドであることを宣言しています。このnewEmployeeメソッドでは、新しい従業員IDを発行するため、従業員データを戻り値として返すことで、発行したIDをクライアントに通知しています。
【8】では、@Consumesアノテーションによって、newEmployeeメソッドが受け取ることのできるデータ形式を指定しています。ここでは、通常のHTMLのFORMを受け取ると定義しています。FORMの各属性の値は、メソッドの引数の@FormParamアノテーションによって取得できます。
【9】では、@PUTアノテーションによって、PUTメソッドによる更新操作を定義しています。PUTでは、従業員IDを指定することを前提にするため、idをURIに含めるように指定します。このメソッドでは返却するデータがないため、戻り値をvoidにしています。その場合、クライアントにはHTTPレスポンスコード「204」(No Content)のみが返却されます。
【10】では、@DELETEアノテーションによって、DELETEメソッドによる従業員削除メソッドを定義しています。
以上が、JAX-RSのリソースクラスの基本的な作成方法となります。アノテーションによって、リクエストパラメータの解析や、レスポンスデータの作成といった定型的なコードが削除され、とてもシンプルなコードになります。
また、今回は割愛しましたが、リクエストパラメータからCookie やHTTPヘッダなどを取得するためのアノテーションも用意しています。
続いて次ページでは、JAX-RSの応用的な使い方を幾つか紹介します。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- Struts後時代のJava EE/Javaモダン開発はどうあるべきか〜JJUG CCC 2014 Springまとめリポート(前編)
Java EEにおいてJava 8はどこまで利用できるのか、Java開発でGit、CI、継続的デリバリは、どこまで有効なのか、Struts後時代のJava EE開発における有効なフレームワークなどをお伝えする。 - 日本の開発者コミュニティが次世代Java仕様策定に貢献、Lambdaを手に入れたJavaテクノロジのその先へ
2015年4月8日、Javaテクノロジに関する開発者イベント「Java Day Tokyo 2015」が開催された。基調講演で紹介されたJavaテクノロジに関する話題を解説していきたい。 - Java 8時代の開発者のためのデバッグ/トラブル解決の基本・応用テクニック〜JJUG CCC 2014 Springまとめリポート(後編)
Java開発における3大トラブルと対策、IDEのデバッガー活用の必要性、Java 8より導入された新しいメモリ領域を使いこなすためのテクニック、独自のトランザクショナルメモリ機構を実装した有効性などをお伝えする。