Alibaba Cloud ECSインスタンス上のJersey Java RESTful APIでアプリを開発する方法

このチュートリアルでは、**Alibaba Cloud Elastic Compute Service**インスタンス上で**Jersey Java RESTful API**を使用してアプリを開発する方法を説明します。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/jersey-java-restful-api-on-an-alibaba-cloud-ecs-instance_591644)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

By Aditya, [Alibaba Cloud Tech Share](https://www.alibabacloud.com/ja/campaign/techshare)著者. [Tech Share](https://www.alibabacloud.com/ja/campaign/techshare)は、技術的な知識やベストプラクティスをクラウドコミュニティ内で共有することを奨励するAlibaba Cloudのインセンティブプログラムです。

デジタル技術の普及に伴い、同じアプリケーションが、ラップトップ、携帯電話、テレビなど、さまざまなデバイスで利用できるようになってきています。構築されている、または構築中のアプリケーションのほとんどは、多階層化されています。多層アプリケーションでは、それぞれのタイプが何を達成できるかが明確に区別されています。これは、それが大幅にコストを削減するように、ビジネスの観点から理にかなっています。しかし、異なるアプリケーション間で同じデータが利用できるという異なるニーズに対応するためには、適切なセキュリティルールでデータにアクセスできる共通の場所が必要です。

開発者の視点から見ると、異なるデバイス間で複製されるデータのニーズの増加と、テクノロジーのシフトは非常に急速に起こっています。バックエンドの変更のための単純なアップグレードのためだけに、システム全体をダウンさせる余裕はありません。また、開発の手間をかけずに新しい技術に適応できるようにしなければなりません。これらの条件をすべて考慮に入れると、RESTフレームワークは、モバイル（AndroidやIOS）やWeb JavaScript技術など、異なる技術でどのようにデータにアクセスできるかという他のレイヤー間の明確な抽象化を提供してくれることがわかります。

REST APIをオンプレミスのサーバーにデプロイするのは非効率的で時間がかかります。代わりに、Alibaba Cloud [Elastic Compute Service](https://www.alibabacloud.com/ja/product/ecs)を利用してJava REST APIをデプロイし、インターネットにサービスを公開する方法を見てみましょう。しかし、APIをクラウドにデプロイする前に、まずAPIを作成する必要がある。ここでは、シンプルなジャージーベースのJava REST APIを作成し、ツールを使ってテストする方法を見ていきます。

###JAVA REST APIの作成
RESTとは「Representational State Transfer」という意味です。RESTは、サーバーとクライアントの間にデカップリングを作り、再利用可能なコンポーネントを維持し、いつでも交換できるようにすることを目的としていました。RESTはステートレスなので、サーバーにキャッシュを実装することで、パフォーマンスや効率を向上させることができます。

では、従業員の詳細を取得＆記録するシンプルなAPIを作成します。

以下、私が開発に使用している完全なツールです。

 JAVA EE開発者のためのEclipse IDE
- 最新のMaven
- Apache Tomcat ウェブサーバ 7
- インソムニアRESTクライアント
- ECSインスタンスのセットアップ

**Alibaba Cloud Consoleにログイン後、Productから[Elastic Compute Instance](https://www.alibabacloud.com/ja/product/ecs)を選択します。**

インスタンスを作成し、できれば最寄りのリージョンで作成します。以下のような手順で進めていきます。私のサーバーの場合は、以下の構成で「Pay-as-you-go」モデルを選択しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/fa657f5f-8454-98cd-8d79-41a67ae9a2ed.png)


[ECSインスタンス](https://www.alibabacloud.com/ja/product/ecs)にWindows 2016 Data Center Imageを使用する予定です。ネットワーキング、システム構成、その他の値をデフォルトに設定しました。Create Instanceをクリックして続行します。

インスタンスが作成されると、コンソールにこんな感じで表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/7797566d-c3cb-5407-19bf-e04bb70c8950.png)

ECS インスタンス名をクリックし、セキュリティグループ > ルールの構成 > セキュリティグループルールの追加を選択します。次の情報を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/baffecb4-3ebb-caba-4e62-70098c8a18dd.png)

ここで注意してほしいのは、8080は私のtomcatがデプロイされている場所です。実際にApache Tomcatが配置されている場所に変更する必要があります。

RDPプロトコル経由でECSインスタンスを接続し、作成したwindows VMを使って開発を進めます。

###APIの作成
最新の「Eclipse IDE for JAVA EE Developers」をダウンロードしてインストールします。

最新版のJDKをインストールし、インストールパスを "JAVA_HOME "と環境変数 "Path "に設定します。
また、mavenをインストールする必要があります。それはとても簡単で、最新のバイナリディストリビューション.zipをダウンロードして解凍し、環境変数 "M2_HOME "と "Path "にインストールパスを設定する必要があります。
この記事の目的のために、コードはzipファイルとして提供されています。プロジェクトをダウンロードしてeclipseワークスペースにインポートしてください。

コードリポジトリはこちらからダウンロードしてください:https://alicloud-common.oss-ap-southeast-1.aliyuncs.com/RESTCodeRepo.zip

ファイル > インポート」からコードをインポートし、ダイアログボックスで「一般」を選択します。

インポートしたコードを見てみましょう。Eclipseでは以下のようなプロジェクト構造になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/c8c96b55-59e9-8c2f-3092-f9a67083a143.png)


完全なプロジェクトのための配置記述子である "pom.xml "に何が含まれているかを見ると、プロジェクトの依存関係を保持しています。

```
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.aditya.restapi</groupId>
    <artifactId>RESTfulExample</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>RESTfulExample Maven WebApplication</name>
    <url>http://maven.apache.org</url>

    <repositories>
        <repository>
            <id>maven2-repository.java.net</id>
            <name>Java.net Repository for Maven</name>
            <url>http://download.java.net/maven/2/</url>
            <layout>default</layout>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.8</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.8</version>
        </dependency>
        
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.8</version>
        </dependency>

    </dependencies>

    <build>
        <finalName>RESTfulExample</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
```

Model-version : 現在の pom が準拠しているバージョンで、maven 3 をサポートするために 4.0.0 にしています。

Artifact Id, packaging, groupID, version, name : これらはパッケージング時に使用し、デプロイ時にプロジェクトを記述するために使用します。

リポジトリ : パッケージング時に使用し、デプロイ時にプロジェクトを記述します。このタグは、依存関係がプルするすべてのリポジトリから構成されています。この下に複数のリポジトリを指定することができます。

依存関係 :このタグはプロジェクトに必要なすべての依存関係から構成されています。APIにはjersey関連のjarを使用し、JUNITのjarも使用しています。

ビルド: ビルドタグには、アプリケーションがどのようにWAR形式にパッケージ化されるか、名前とどのバージョンのmavenアセンブリプラグインがパッケージ化に使用されるかの完全な情報が含まれています。

受信して送信するデータを保持するモデルが必要なので、名前、年齢、給与、会社を保持する Employee.java モデルを作成しました。

```
package com.aditya.model;

public class Employee {

    private String name;
    private String age;
    private int salary;
    private String company;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
    
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    public String getCompany() {
        return company;
    }
    public void setCompany(String company) {
        this.company = company;
    }
    @Override
    public String toString() {
        return "Employee [name=" + name + ", age=" + age + ", salary=" + salary + ", company=" + company + "]";
    }
}
```

このモデルは、情報の取得、保存、表示のためのゲッター、セッター、toString()メソッドで構成されています。

REST APIの完全なコードを持つ "JSONService.java "の "com.aditya.rest "パッケージの中にあります。

```
package com.aditya.rest;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.aditya.model.Employee;

@Path("/json/empservice")
public class JSONService {

    @GET
    @Path("/get")
    @Produces(MediaType.APPLICATION_JSON)
    public Employee getEmpDetails() {

        Employee emp = new Employee();
        emp.setName("Aditya");
        emp.setCompany("ABC Corporation");
        emp.setAge("31");
        emp.setSalary(1000);

        return emp;

    }

    @POST
    @Path("/post")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createEmpInJSON(Employee emp) {
        
        String result = "Employee saved : " + emp.toString();
        return Response.status(201).entity(result).build();
        
    }
    
}
```

我々は最初にパッケージ宣言を持っている＆我々はまた、すべてのインポート＆アノテーションがジャージーのjarからインポートされていることに気づきます。

初期パスは、マップとクラスをマップし、メソッドは@GET / @POSTによって識別されます。

@GET：

我々は@GETがハードコードされたデータの情報を返すgetEmpDetails()にマップされていることを確認してください。これで自動的にアンマーシャリング(JAVAオブジェクトからJSONへの変換)が行われます。これがジャージーサーブレットの利点です。その方法を見てみましょう。

@POST：

@POSTには、ジャージーサーブレットへのリクエストからマーシャリングされたObjectをempオブジェクトに受け取るcreateEMPInJSON()がマッピングされています。レスポンスは結果とともにステータス201(Created)で作成されます。

Web.xml

```
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>Restful Web Application</display-name>

    <servlet>
        <servlet-name>jersey-serlvet</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.aditya.rest</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

</web-app>
```

これはAPIのデプロイメント記述子です。display-nameはアプリケーションの名前から構成されているので、明らかです。これは私たちが使用するサーブレット名で構成され、サーブレットクラスはサーブレットの完全修飾名で構成されています。

また、param-nameとparam-valueにはウェブアプリケーションに必要な機能を指定しています。

com.sun.jersey.api.json.POJOMappingFeatureは、JSONをjavaオブジェクトにマッピングする機能を提供します。

サーブレットマッピングはサーブレット機能を特定の URL パターンにマッピングします。

###Apache Tomcat 7：
公式リンクからWindowsインストーラをダウンロードしてください。
[https://tomcat.apache.org/download-70.cgi](https://tomcat.apache.org/download-70.cgi?spm=a2c65.11461447.0.0.decc2baan0qMRA&file=download-70.cgi)

Tomcat7.exeを実行し、Tomcat7をインストールしたいフォルダを指定してください。

###APIのデプロイとテスト：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/48779e4b-c472-df7e-bfba-90876e1ec2a2.png)


サーバーセクションを右クリックして、"新規作成 > サーバー "を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/74cd2bec-0e12-9d74-a7fe-afd37528b19a.png)

「Tomcat 7 Server」を選択して「次へ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/905938ee-0a89-bc5d-0579-56f4eab2a9f1.png)


「参照」を選択して、tomcat のインストールフォルダを指定すると、サーバーが作成されます。

プロジェクトを右クリックして "Run as" > "Run on server "を選択します。APIがデプロイされると、以下のような状態になります。

参照」を選択して、tomcat のインストールフォルダを指定すると、サーバーが作成されます。

プロジェクトを右クリックして "Run as" > "Run on server "を選択します。APIがデプロイされると、以下のような状態になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/ad7e63b3-adb7-8827-a06c-72d326947a03.png)


Insomnia Clientをインストールし、新しいリクエストを作成し、以下のURIを使用します。

GET : http://localhost:8080/RESTfulExample/rest/json/empservice/get

POST : http://localhost:8080/RESTfulExample/rest/json/empservice/post

以下のような反応が見られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/a9df51ae-9111-18bf-376d-8bbd3d304a38.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/1dfa35ac-4ea5-3462-72ee-9d58938448ec.png)


また、ECSインスタンスのパブリックIPを使用して同じAPIにアクセスすることができますが、それを変更してもAPIのURLは変更されません。

GET - [http://:8080/RESTfulExample/rest/json/empservice/get](https://www.alibabacloud.com/blog/jersey-java-restful-api-on-an-alibaba-cloud-ecs-instance_591644)

POST - [http://:8080/RESTfulExample/rest/json/empservice/post](https://www.alibabacloud.com/blog/jersey-java-restful-api-on-an-alibaba-cloud-ecs-instance_591644)

###追加ステップ
1.本番環境では、コンソールベースのアクセスのみを提供するバージョン1709のWindowsサーバーイメージを使用することでコストを削減することができますが、[ECSインスタンス](https://www.alibabacloud.com/ja/product/ecs)上の多くのソフトウェアを削減し、パフォーマンスを向上させることができます。

2.あなたはまた、我々は複数のECSイメージを使用して、それをスケールアップすることを計画しているのAPIのためのサーバーのロードバランサーを使用する必要があります。

3.悪用を防止し、セキュリティを高めるために、APIにOAuthのような認証を導入することができます。

4.また、APIのセキュリティ機能を向上させるために、[Alibaba Cloud DNS](https://www.alibabacloud.com/ja/product/dns)と[Anti-DDOS Pro](https://www.alibabacloud.com/ja/product/ddos-pro)の使用を検討することができます。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*