JavaによるRestful Webサービスのチュートリアル
JavaでのRestful Webサービスチュートリアルへようこそ。RESTはREpresentational State Transferの略です。RESTはネットワークを通じてアクセスできるアプリケーションを開発するためのアーキテクチャスタイルです。RESTアーキテクチャスタイルは、2000年にロイ・フィールディングが彼の博士論文で紹介しました。
安らかなウェブサービス
レストフルなウェブサービスは、ウェブサービスがリソースとして識別され、それぞれのURIによってアクセスされる状態を持たないクライアントサーバーアーキテクチャです。レストクライアントアプリケーションは、HTTPのGET/POSTメソッドを使用してレストフルなウェブサービスを呼び出すことができます。レストは使用する特定のプロトコルを指定していませんが、ほとんどの場合、HTTP/HTTPSを使用します。SOAPウェブサービスと比較すると、これらは軽量で、標準に従っていません。リクエストとレスポンスにはXML、JSON、テキストやその他のデータ形式を使用することができます。
JavaのRESTfulなWebサービスAPI
RESTful Webサービスを作成するためのJava API(JAX-RS)は、Webサービスの開発と展開を簡素化するためにアノテーションを使用しています。JAX-RSはJDKの一部なので、アノテーションを使用するために何も追加する必要はありません。
レストフルなウェブサービスのアノテーション
いくつかの重要なJAX-RSのアノテーションは次のとおりです。
- @Path: used to specify the relative path of class and methods. We can get the URI of a webservice by scanning the Path annotation value.
- @GET, @PUT, @POST, @DELETE and @HEAD: used to specify the HTTP request type for a method.
- @Produces, @Consumes: used to specify the request and response types.
- @PathParam: used to bind the method parameter to path value by parsing it.
レストフルなウェブサービスとSOAP
-
- SOAPはプロトコルであり、RESTはアーキテクチャのスタイルです。
-
- SOAPのサーバーとクライアントのアプリケーションはWSDL契約によって密接に結びついていますが、RESTウェブサービスとクライアントには契約がありません。
-
- SOAPウェブサービスと比較すると、RESTの学習曲線は簡単です。
-
- RESTウェブサービスのリクエストとレスポンスのタイプはXML、JSON、テキストなどですが、SOAPはXMLのみです。
- JAX-RSはRESTウェブサービスのためのJava APIで、JAX-WSはSOAPウェブサービスのためのJava APIです。
REST APIの実装
JAX-RS APIには、2つの主要な実装があります。
-
- Jersey: ジャージはサンが提供するリファレンス実装です。JAX-RSの実装としてJerseyを使用するには、web.xmlでそのサーブレットを設定し、必要な依存関係を追加する必要があります。なお、JAX-RS APIはJerseyではなくJDKの一部であるため、アプリケーションにその依存関係のJARファイルを追加する必要があります。
- RESTEasy: RESTEasyはJAX-RSの実装を提供するJBossプロジェクトです。
JavaのRestful Webサービスのチュートリアル
JerseyとRESTEasyを使用して、どれくらい簡単にRestful Webサービスを作成できるか見てみましょう。HTTPを介して以下のメソッドを公開し、Chrome Postman拡張機能を使用してこれらをテストします。
URI | HTTP Method | Description |
---|---|---|
/person/{id}/getDummy | GET | Returns a dummy person object |
/person/add | POST | Adds a person |
/person/{id}/delete | GET | Delete the person with ‘id’ in the URI |
/person/getAll | GET | Get all persons |
/person/{id}/get | GET | Get the person with ‘id’ in the URI |
JerseyのRestful Webサービス
動的なウェブプロジェクトを作成し、それをMavenに変換してウェブサービスプロジェクトの骨組みを取得します。下の画像は最終プロジェクトの構造を示しています。pom.xmlファイルには、Jerseyの依存関係が表示されています。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>JAXRS-Example</groupId>
<artifactId>JAXRS-Example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.19</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
ジャージクライアントの依存関係を追加する必要はありませんが、Jerseyを使用してRESTウェブサービスを呼び出すJavaプログラムを書いている場合は必要です。次に、デプロイメント記述子を見て、Jerseyを設定してウェブアプリケーションを作成する方法を学びましょう。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>JAXRS-Example</display-name>
<!-- Jersey Servlet configurations -->
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.scdev</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- Jersey Servlet configurations -->
</web-app>
私たちのWebアプリケーションにJerseyをプラグインするために必要なことは以上です。JavaのコードではJAX-RSアノテーションを使用します。initパラメータcom.sun.jersey.config.property.packagesの値には、Webサービスのリソースとメソッドがスキャンされるパッケージを指定してください。
モデルのクラスのRESTの例
まず、アプリケーションのデータ用にPersonというモデルビーンと、クライアントシステムへのレスポンス送信用にResponseというモデルビーンを作成します。XMLのレスポンスを送信するため、これらのビーンには@XmlRootElementのアノテーションを付ける必要があります。そのため、このクラスが存在します。
package com.scdev.jaxrs.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement (name="person")
public class Person {
private String name;
private int age;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString(){
return id+"::"+name+"::"+age;
}
}
package com.scdev.jaxrs.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Response {
private boolean status;
private String message;
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
RESTウェブサービスのチュートリアルサービス
私たちのURIの構造に基づいて、以下はサービスインターフェースとその実装コードです。
package com.scdev.jaxrs.service;
import com.scdev.jaxrs.model.Person;
import com.scdev.jaxrs.model.Response;
public interface PersonService {
public Response addPerson(Person p);
public Response deletePerson(int id);
public Person getPerson(int id);
public Person[] getAllPersons();
}
package com.scdev.jaxrs.service;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.scdev.jaxrs.model.Person;
import com.scdev.jaxrs.model.Response;
@Path("/person")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public class PersonServiceImpl implements PersonService {
private static Map<Integer,Person> persons = new HashMap<Integer,Person>();
@Override
@POST
@Path("/add")
public Response addPerson(Person p) {
Response response = new Response();
if(persons.get(p.getId()) != null){
response.setStatus(false);
response.setMessage("Person Already Exists");
return response;
}
persons.put(p.getId(), p);
response.setStatus(true);
response.setMessage("Person created successfully");
return response;
}
@Override
@GET
@Path("/{id}/delete")
public Response deletePerson(@PathParam("id") int id) {
Response response = new Response();
if(persons.get(id) == null){
response.setStatus(false);
response.setMessage("Person Doesn't Exists");
return response;
}
persons.remove(id);
response.setStatus(true);
response.setMessage("Person deleted successfully");
return response;
}
@Override
@GET
@Path("/{id}/get")
public Person getPerson(@PathParam("id") int id) {
return persons.get(id);
}
@GET
@Path("/{id}/getDummy")
public Person getDummyPerson(@PathParam("id") int id) {
Person p = new Person();
p.setAge(99);
p.setName("Dummy");
p.setId(id);
return p;
}
@Override
@GET
@Path("/getAll")
public Person[] getAllPersons() {
Set<Integer> ids = persons.keySet();
Person[] p = new Person[ids.size()];
int i=0;
for(Integer id : ids){
p[i] = persons.get(id);
i++;
}
return p;
}
}
ほとんどのコードは自己解明的ですので、JAX-RSアノテーション(@Path、@PathParam、@POST、@GET、@Consumes、@Produces)に慣れるために時間をかけてください。
レストフルウェブサービスのテスト
それで終わりです。私たちのウェブサービスは準備ができていますので、WARファイルとしてエクスポートしてTomcatのwebappsディレクトリに配置するか、選択した他のコンテナにデプロイしてください。以下は、このウェブサービスのテストの一部です。なお、リクエストヘッダーにAcceptとContent-Typeの値を「application/xml」として提供する必要があることに注意してください (下の画像に示すように)。
- getDummy
- add
- get
- getAll
- delete
Jersey JAX-RSの実装を使用してウェブサービスを作成するのは以上です。お分かりいただけるように、ほとんどのコードはJAX-RSのアノテーションを使用し、Jerseyはデプロイメント記述子と依存関係を通じてプラグインされています。
RESTEasyのRESTful Webサービスの例
ジャージープロジェクトで開発されたすべてのビジネスロジックを使用する予定ですが、同じプロジェクトに変更を加える代わりに、新しいプロジェクトを作成しました。動的なウェブプロジェクトを作成し、それをMavenプロジェクトに変換してください。そして、JavaクラスであるPerson、Response、PersonService、PersonServiceImplをすべてコピーしてください。以下は、すべての変更が完了した後の最終プロジェクトです。pom.xmlファイルに以下のRESTEasyの依存関係を追加してください。
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.13.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.13.Final</version>
</dependency>
以下は、Resteasyサーブレットを設定しているweb.xmlファイルです。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>JAXRS-Example-RestEasy</display-name>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.scdev.jaxrs.resteasy.app.MyApp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
以下のように、init-paramでMyAppクラスを値として指定していることに注意してください。ここでは、javax.ws.rs.core.Applicationクラスを拡張しています。
package com.scdev.jaxrs.resteasy.app;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import com.scdev.jaxrs.service.PersonServiceImpl;
public class MyApp extends Application {
private Set<Object> singletons = new HashSet<Object>();
public MyApp() {
singletons.add(new PersonServiceImpl());
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
RESTEasyウェブサービステスト
それで終わりです。私たちのウェブサービスは、RESTEasy JAX-RSの実装が完了しました。以下は、Postman Chrome拡張機能のテストのいくつかの出力例です。
- getDummy
- add
- get
それが、Restful Webサービスチュートリアルのすべてです。JAX-RSアノテーションについて学んで、コードの再利用とJerseyからRESTEasyへのスムーズな移行の利点を理解していただけたことを願っています。