Java Servlet Webアプリで Hello World する

# Java Servlet Webアプリで Hello World する

こんにちは、@studio_meowtoon です。今回は、WSL の Ubuntu 22.04 で Java Servlet Web アプリケーションを作成して Hello World を表示する方法を紹介します。
![java_on_jetty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/6c02ecfb-266c-69eb-ceff-d35ac3c1efa7.png)

## 目的

Windows 11 の Linux でクラウド開発します。

こちらから記事の一覧がご覧いただけます。

https://qiita.com/studio_meowtoon/items/6119ab05d8b13527efd8

## 実現すること

ローカル環境の Ubuntu で、Java Servlet war ファイル形式のアプリをビルド、起動します。

:::note warn
**Java Servlet** は、Web アプリケーションの基本的な要素を学ぶ上で重要です。しかし、現状では **Servlet をそのまま使用することは少なくなっています**。それでも、Servlet を使った Web アプリケーションを自分で作成し、ビルドして動作させることは、学習に役立ちます。初心者の方も、ぜひチャレンジしてみてください。
:::

## 技術トピック

### Java Servlet とは？  

<details>
<summary>こちらを展開してご覧いただけます。</summary>

### [Java Servlet](https://docs.oracle.com/javaee/7/tutorial/servlets.htm#BNAFD)

:::note info
Java Servlet は、Java プログラムによって動作するサーバーサイドの WEB コンポーネントであり、HTTP リクエストを受信して HTTP レスポンスを生成する機能を提供します。  

以下は Java Servlet の主な特徴とメリットです。  

|特徴やメリット|内容|
|:--|:--|
|プラットフォームの独立性|Java Servlet は Java で開発されており、プラットフォームに依存しないため、どのオペレーティングシステム上でも動作することができます。|
|大規模な Web アプリケーションの開発が可能|Java Servlet を使用することで、大規模な Web アプリケーションを開発することができます。Java Servlet は、スケーラビリティやセキュリティなど、高度な機能を提供するため、大規模な Web アプリケーションの開発に最適です。|
|リクエストとレスポンスの制御|Java Servlet は、HTTP リクエストとレスポンスを制御することができます。つまり、クライアントから送信されたリクエストを処理し、必要に応じて HTTP レスポンスを生成することができます。|
|セッション管理|Java Servlet は、セッション管理をサポートするため、Web アプリケーションでユーザーの状態を管理することができます。|
|プログラマブルなAPI|Java Servlet は、プログラマブルな API を提供するため、開発者が Web アプリケーションの振る舞いを制御することができます。また、Java Servlet は、多数のサードパーティ製ライブラリをサポートするため、Web アプリケーションの開発を容易にします。|
:::

</details>

## 開発環境

+ Windows 11 Home 22H2 を使用しています。  

:::note info
[WSL](https://learn.microsoft.com/ja-jp/windows/wsl/about) の Ubuntu を操作していきますので macOS の方も参考にして頂けます。  
:::

<details>

WSL (Microsoft Store アプリ版) [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/2aaa6579cb8e4fa1d874)

```sh
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
```

Ubuntu [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/2aaa6579cb8e4fa1d874)

```sh
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
```

Java JDK [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/4d11e94a2389758759cd)

```sh
$ java -version
openjdk version "11.0.18" 2023-01-17
OpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu122.04)
OpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu122.04, mixed mode, sharing)
```

Maven [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/f4cdc4039158153365fb)

```sh
$ mvn -version
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.18, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
```

</details>

:::note warn
この記事では基本的に **Ubuntu のターミナルで操作**を行います。**Vim を使用してコピペする方法**を初めて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。
:::

https://qiita.com/studio_meowtoon/items/7771ad48676926e41463

## 作成する Web アプリケーションの仕様

|No|リクエストURL|HTTPメソッド|MIME タイプ|
|:--|:--|:--|:--|
|1|/hello|GET|text/html|

:::note info
"/hello" というリクエストURLに対して HTTP GET リクエストを送信すると、HTMLがレスポンスされるシンプルな Web アプリを実装します。
:::

## Hello World を表示する手順

### プロジェクトの作成

プロジェクトフォルダを作成します。  
※ ~/tmp/hello-servlet をプロジェクトフォルダとします。  

```sh
$ mkdir -p ~/tmp/hello-servlet
$ cd ~/tmp/hello-servlet
```

### Servlet クラスの作成

Servlet クラスを作成します。

```sh
$ mkdir -p src/main/java/com/example/servlet
$ vim src/main/java/com/example/servlet/HelloServlet.java
```

ファイルの内容

```java:HelloServlet.java
package com.example.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("message", "Hello World!");
        request.getRequestDispatcher("/WEB-INF/views/hello.jsp").forward(request, response);
    }
}
```

<details>
<summary>説明を開きます。</summary>

:::note info
このコードは Java Servlet を実装しています。

|内容|
|:--|
|@WebServlet アノテーションを使用して、"/hello" のリクエストパスにマッピングされた Servlet クラスを作成しています。|
|HelloServlet は、doGet() メソッドをオーバーライドし、HttpServletRequest と HttpServletResponse を受け取ります。|
|リクエスト属性に "message" という名前の文字列を設定し、JSP ファイルにフォワードします。|
|JSP ファイルは、設定されたメッセージを表示するために使用されます。|
|Servlet API は、Web アプリケーションの開発を簡素化し、再利用可能なコンポーネントの作成を可能にする多数のクラスとインタフェースを提供しています。|
:::

</details>

### JSP ファイルの作成

JSP ファイルを作成します。

```sh
$ mkdir -p src/main/webapp/WEB-INF/views
$ vim src/main/webapp/WEB-INF/views/hello.jsp
```

ファイルの内容

```jsp:hello.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h1><c:out value="${message}" /></h1>
    </body>
</html>
```

<details>
<summary>説明を開きます。</summary>

:::note info
このコードは、JSTL (JSP Standard Tag Library) を使用して、Java Servlet によって設定されたリクエスト属性の値を表示するための JSP (JavaServer Pages) を作成しています。  

|内容|
|:--|
|この JSP では、リクエスト属性 "message" の値を取得し、h1 要素に表示しています。 | 
|また、JSTL の c:out タグを使用して、HTML エスケープされたメッセージを表示するためのセキュリティ対策が行われています。|
:::

</details>

### pom.xml の作成

pom.xml ファイルを作成します。

```sh
$ vim pom.xml
```

ファイルの内容

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>hello-servlet</artifactId>
    <packaging>war</packaging>
    <version>1.0</version>
    <name>hello-servlet</name>

    <properties>
        <javax.servlet.version>4.0.1</javax.servlet.version>
        <java.version>11</java.version>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!-- Servlet -->
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${javax.servlet.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>${name}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>10.0.13</version>
                <configuration>
                    <scanIntervalSeconds>10</scanIntervalSeconds>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
```

<details>
<summary>説明を開きます。</summary>

:::note info
Maven プロジェクトのプロジェクトオブジェクトモデル (POM) です。プロジェクトの情報、依存関係、ビルド設定などが含まれています。

各項目は以下のとおりです。

|項目|内容|
|:--|:--|
|groupId|プロジェクトのグループIDを定義します。|
|artifactId|プロジェクトのアーティファクトIDを定義します。|
|packaging|プロジェクトのパッケージングタイプを定義します。(例えば、jar、war、pom など)|
|version|プロジェクトのバージョンを定義します。|
|name|プロジェクトの表示名を定義します。|
|properties|プロジェクトで使用されるプロパティー値を定義します。|
|javax.servlet.version|サーブレット API のバージョンを定義します。|
|java.version|Java のバージョンを定義します。|
|failOnMissingWebXml|web.xml ファイルが存在しない場合に、ビルドエラーを出力するかどうかを設定するプロパティーです。|
|dependencies|依存関係のリストを定義します。ここでは、Web アプリケーションで使用される Servlet や JSP のライブラリに依存しています。|
|build|プロジェクトのビルド設定を定義します。ここでは、Maven コンパイラプラグインを使用して Java バージョン11 でコンパイルするように指定し、Jetty Web サーバを Maven プラグインとして使用できるようにします。また、最終的に生成される WAR ファイルの名前を ${name} に設定しています。|
:::

</details>

### ディレクトリ・ファイル構成

プロジェクトのファイル構成を表示してみます。

```sh
$ tree
.
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── servlet
        │               └── HelloServlet.java
        └── webapp
            └── WEB-INF
                └── views
                    └── hello.jsp
```

### Java Servlet アプリをビルド、実行

Java アプリをビルドします。
※ target/hello-servlet.war ファイルが作成されます。  

```sh
$ mvn clean package
```

アプリを起動します。 (※ ctrl + C で停止します)

```sh
$ mvn jetty:run
```

:::note info
**mvn jetty:run** コマンドは、Maven のプラグインにより Jetty Web サーバーを一時的に立ち上げ、その中で war ファイル形式の Web アプリケーションが実行されます。  
:::

WEBブラウザで確認します。

```sh
http://localhost:8080/hello
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/b84f6bc2-3d9b-024f-b094-aab6763fb776.png)
WEBブラウザに "Hello World!" と表示することが出来ました。

## まとめ

Ubuntu に構築したシンプルな Java 開発環境で、Java Servlet Web アプリを実行することができました。

:::note warn
実際の業務での Java Servlet の使用ケースでは、構成ファイルなどが追加されるため、ここで示したようなシンプルな構成とは異なる場合があります。しかしながら、最小構成の例を学ぶことで、Java Servlet Web アプリがどのような構成が必要なのかを理解することができます。
:::

どうでしたか？ WSL Ubuntu で、Java Servlet Web アプリケーションを手軽に実行することができます。ぜひお試しください。今後も Java の開発環境などを紹介していきますので、お楽しみに。それでは失礼します。