Apache Tomcat 9 + Java Servlet + JSP で Hello World

## 概要

- Java Servlet と JSP を含む WAR ファイルを Gradle で作成する
- Apache Tomcat 9 をインストールする
- WAR ファイルを Apache Tomcat 9 にデプロイする

## 今回の環境

- Apache Tomcat 9.0.37 (Java Servlet 4.0, JSP 2.3)
- Java 14 (AdoptOpenJDK 14.0.1)
- Gradle 6.5.1
- macOS 10.15 Catalina

## Java Servlet と JSP を含む WAR ファイルを Gradle で作成する

### ソースコードを置くディレクトリを用意する

今回は任意のディレクトリに mywebapp というディレクトリを作成してその中にシンプルなサンプルコードを用意する。

```
$ mkdir mywebapp

$ cd mywebapp
```

### ファイル一覧

```
mywebapp
├── build.gradle
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── MyServlet.java
        └── webapp
            ├── WEB-INF
            │   └── web.xml
            └── myjsp.jsp
```

### build.gradle

```groovy
plugins {
  id 'war'
}

repositories {
  mavenCentral()
}

dependencies {
  // Java Servlet 4.0 API
  // https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api
  providedCompile 'javax.servlet:javax.servlet-api:4.0.1'
}

// Java 14
sourceCompatibility = 14
targetCompatibility = 14

// Application
version = '1.0'
```

### src/main/java/com/example/MyServlet.java

```java
package com.example;

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

@WebServlet("/myservlet")
public class MyServlet extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
    res.setContentType("text/html; charset=utf-8");
    try (PrintWriter out = res.getWriter()) {
      out.println("<html><body>");
      out.println("サーブレット: Hello Servlet World!<br>");
      out.println(getServletContext().getServerInfo());
      out.println("</body></html>");
    }
  }
}
```

### src/main/webapp/myjsp.jsp

```jsp
<%@ page contentType="text/html; charset=utf-8" %><html><body>
ジェイエスピー: Hello JSP World!<br>
<%= pageContext.getServletContext().getServerInfo() %><br>
java.vm.name: <%= System.getProperty("java.vm.name") %><br>
java.vm.vendor: <%= System.getProperty("java.vm.vendor") %><br>
java.vm.version: <%= System.getProperty("java.vm.version") %><br>
</body></html>
```

### src/main/webapp/WEB-INF/web.xml

```xml
<?xml version="1.0" encoding="UTF-8"?>

<!-- Web Application Deployment Descriptor (Java Servlet 4.0) -->
<web-app
  xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0">

  <servlet>
    <servlet-name>myjsp</servlet-name>
    <jsp-file>/myjsp.jsp</jsp-file>
  </servlet>

  <servlet-mapping>
    <servlet-name>myjsp</servlet-name>
    <url-pattern>/myjsp</url-pattern>
  </servlet-mapping>

</web-app>
```

### WAR ファイルを作成する

Gradle の build タスクで WAR ファイルを作成する。

```
$ gradle build
```

WAR ファイルが生成されていることを確認する。

```
$ file build/libs/mywebapp-1.0.war
build/libs/mywebapp-1.0.war: Zip archive data, at least v1.0 to extract
```

## Apache Tomcat 9 をインストールする

### インストールするディレクトリを用意する

今回は任意のディレクトリに tomcat9 というディレクトリを作成してその中にインストールする。

```
$ mkdir tomcat9

$ cd tomcat9
```

### Apache Tomcat 9 をダウンロードして展開する

[Apache Tomcat® \- Apache Tomcat 9 Software Downloads](https://tomcat.apache.org/download-90.cgi)

```
$ wget https://downloads.apache.org/tomcat/tomcat-9/v9.0.37/bin/apache-tomcat-9.0.37.tar.gz

$ tar xf apache-tomcat-9.0.37.tar.gz
```

### 起動用の Java VM を用意する

環境変数 JAVA_HOME を設定する。

```
$ export JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-14.jdk/Contents/Home

$ PATH=${JAVA_HOME}/bin:${PATH}

$ java -version
openjdk version "14.0.1" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 14.0.1+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 14.0.1+7, mixed mode, sharing)
```

### Apache Tomcat 9 が起動することを確認する

startup.sh で Apache Tomcat 9 を起動する。

```
$ ./apache-tomcat-9.0.37/bin/startup.sh
Using CATALINA_BASE:   /Users/foo/tomcat9/apache-tomcat-9.0.37
Using CATALINA_HOME:   /Users/foo/tomcat9/apache-tomcat-9.0.37
Using CATALINA_TMPDIR: /Users/foo/tomcat9/apache-tomcat-9.0.37/temp
Using JRE_HOME:        /Library/Java/JavaVirtualMachines/adoptopenjdk-14.jdk/Contents/Home
Using CLASSPATH:       /Users/foo/tomcat9/apache-tomcat-9.0.37/bin/bootstrap.jar:/Users/foo/tomcat9/apache-tomcat-9.0.37/bin/tomcat-juli.jar
Tomcat started.
```

curl でアクセスして起動していることを確認する。

```
$ curl --include -s http://localhost:8080/ | head -15
HTTP/1.1 200 
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 12 Jul 2020 10:38:03 GMT




<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Apache Tomcat/9.0.37</title>
        <link href="favicon.ico" rel="icon" type="image/x-icon" />
        <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
```

shutdown.sh で Apache Tomcat 9 を停止する。

```
$ ./apache-tomcat-9.0.37/bin/shutdown.sh
Using CATALINA_BASE:   /Users/foo/tomcat9/apache-tomcat-9.0.37
Using CATALINA_HOME:   /Users/foo/tomcat9/apache-tomcat-9.0.37
Using CATALINA_TMPDIR: /Users/foo/tomcat9/apache-tomcat-9.0.37/temp
Using JRE_HOME:        /Library/Java/JavaVirtualMachines/adoptopenjdk-14.jdk/Contents/Home
Using CLASSPATH:       /Users/foo/tomcat9/apache-tomcat-9.0.37/bin/bootstrap.jar:/Users/foo/tomcat9/apache-tomcat-9.0.37/bin/tomcat-juli.jar
NOTE: Picked up JDK_JAVA_OPTIONS:  --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
```

## WAR ファイルを Apache Tomcat 9 にデプロイする

### WAR ファイルを Apache Tomcat 9 の webapps ディレクトリに設置する

```
$ cp mywebapp/build/libs/mywebapp-1.0.war tomcat9/apache-tomcat-9.0.37/webapps/mywebapp.war
```

### Apache Tomcat 9 を起動する

```
$ ./tomcat9/apache-tomcat-9.0.37/bin/startup.sh
```

### Java Servlet と JSP にアクセスする

curl で Java Servlet にアクセスして動作を確認する。

```
$ curl --include http://localhost:8080/mywebapp/myservlet
HTTP/1.1 200 
Content-Type: text/html;charset=utf-8
Content-Length: 94
Date: Sun, 12 Jul 2020 13:06:56 GMT

<html><body>
サーブレット: Hello Servlet World!<br>
Apache Tomcat/9.0.37
</body></html>
```

curl で JSP にアクセスして動作を確認する。

```
$ curl --include http://localhost:8080/mywebapp/myjsp.jsp
HTTP/1.1 200 
Set-Cookie: JSESSIONID=EE7C8309A86FBBEDBCEB618759FF6022; Path=/mywebapp; HttpOnly
Content-Type: text/html;charset=utf-8
Content-Length: 204
Date: Sun, 12 Jul 2020 13:07:08 GMT

<html><body>
ジェイエスピー: Hello JSP World!<br>
Apache Tomcat/9.0.37<br>
java.vm.name: OpenJDK 64-Bit Server VM<br>
java.vm.vendor: AdoptOpenJDK<br>
java.vm.version: 14.0.1+7<br>
</body></html>
```

## 参考資料

- [Apache Tomcat 9 \(9\.0\.37\) \- Documentation Index](https://tomcat.apache.org/tomcat-9.0-doc/)
- [Apache Tomcat® \- Which Version Do I Want?](https://tomcat.apache.org/whichversion.html)
- [The Java Community Process\(SM\) Program \- JSRs: Java Specification Requests \- detail JSR\# 369: Java Servlet 4.0 Specification](https://jcp.org/en/jsr/detail?id=369)
- [The Java Community Process\(SM\) Program \- JSRs: Java Specification Requests \- detail JSR\# 245: JavaServer Pages 2.1](https://jcp.org/en/jsr/detail?id=245)
- [Overview \(Servlet 4\.0 API Documentation \- Apache Tomcat 9\.0\.37\)](https://tomcat.apache.org/tomcat-9.0-doc/servletapi/)
- [Overview \(JSP 2\.3 API Documentation \- Apache Tomcat 9\.0\.37\)](https://tomcat.apache.org/tomcat-9.0-doc/jspapi/)
- [Java EE: XML Schemas for Java EE Deployment Descriptors](http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html)