今更Spring framework+JettyでHelloWorld Webアプリを作る

タイトル通りですが、10年ぶりにJavaを仕事で触る機会ができたので、今のうちに自習します。
稼働中の既存システムの勉強なので、最新の技術スタックではなく、ちょっと古めの組み合わせです。

Webアプリはデプロイせず、ローカルで実行するだけ。

# 使うツールと筆者の知識レベル。
- Mac book Pro
    - 使い始めて半年くらい。私生活はほぼWindows。
- Java
    - 約10年ぶりに触る。3年くらい触ってた。当時はちょうどJava8が発表されたくらいか。
- Maven
    - 大昔にちょっとだけ触ったことがある。当時のメインはAntだった。今はGradleの方が主流？
- Spring framework
    - 名前は知ってる。当時はStrutsも多かったが、今はSpring bootなのだろう。
- IntelliJ IDEA Community
    - 名前は知ってる。当時はEclipseしか使っていなかった。
- Jetty Server
    - JavaはTomcat以外で使ったことがなかった

# 環境準備

Javaは以前に入れてあったので、そのまま使う。大人の事情で14でも11でもなく、Java8。

```sh
$ java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
```

とりあえずmacなので、brewでMavenを入れる。

```sh
$ brew install maven
(略)
$ mvn -v
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
(略)
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.6", arch: "x86_64", family: "mac"
```

## IntelliJのインストール

IntelliJ IDEA Communityもインストール。GUIで入れたので方法は省略。

好みに応じて設定を変える。
ここが参考になった。 https://www.karakaram.com/intellij-idea-always-do-things/

自分は基本はそのままで使うスタイルなのだけれど、精神衛生上よろしくないので、Keymapだけ少しいじった(特にC-h,C-d)。


# プロジェクト作成

とりあえずGitHubに空のプロジェクトを作って、それをcloneしておく。ここが作業ディレクトリ。

```sh
$ git clone https://github.com/sekikatsu36/spring-sample.git
$ cd spring-sample
$ git config --local user.name "sekikatsu36"
$ git config --local user.email "(略)"
```

IntelliJでMavenの新規プロジェクトを作成。特に設定は変更せず、デフォルトのまま。

<img width="1350" alt="スクリーンショット 2020-06-27 13.29.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299048/6652aabf-c168-6019-9c79-8e869ada32bf.png">

<img width="1350" alt="スクリーンショット 2020-06-27 13.36.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299048/e7b140f5-b56f-87a0-a637-497d70e57fa8.png">


これで初期状態が完成。

```sh
$ ls -a
.			.DS_Store		.gitignore		pom.xml			src
..			.git			.idea			spring-sample.iml
```

# spring frameworkの設定

Webにはspring bootの記事が多く、spring frameworkは少なめ。
とはいえ、今はspring frameworkが必要なので、使えるようにするために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>org.example.api</groupId>
    <artifactId>spring-sample</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <!--  pom.xml内でバージョンを変数的に扱えるようにする -->
        <spring.version>5.2.5.RELEASE</spring.version>
        <jetty.version>9.4.11.v20180605</jetty.version>
    </properties>

    <dependencies>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- jetty -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.14.v20181114</version>
            </plugin>
        </plugins>
    </build>
</project>
```

最初の段階では、`properties`と`dependencies`だけ書いてた。それ以外の点については後で追加説明する。

## 参照でエラーが出た場合

自分の環境の場合、`org.springframework.spring-webmvc:5.2.5.RELEASE`が見つからないというエラーが出た。
[リポジトリ](https://mvnrepository.com/artifact/org.springframework/spring-webmvc/5.2.5.RELEASE)には存在している。


以下を実行

```sh
mvn clean install
```

結果

- ログに `Downloaded from central: https://repo.maven.apache.org/maven2/org/springframework/spring-webmvc/5.2.5.RELEASE/spring-webmvc-5.2.5.RELEASE.jar` が表示された
- `/Users/(ユーザ名)/.m2/repository/org/springframework/spring-webmvc/5.2.5.RELEASE` が追加された
- IntelliJ ではエラーが表示されたままだったが、Mavenのリロードをしたらエラーが消えた

# ソースを書く

基本的に https://qiita.com/kasa_le/items/6aaf17823db67c951fb0 の通りにやればいい。
ただし、こちらの記事は`IntelliJ IDEA Ultimate`なので、 `IDEA Community`では[Viewの作成](https://qiita.com/kasa_le/items/6aaf17823db67c951fb0#view%E3%81%AE%E4%BD%9C%E6%88%90)以降はこのまま動かない。

とりあえず、コントローラの作成とviewフォルダの作成まではこの通りに終わらせる。
以下ができている状態。

```
/src/main
  /java/org/example/controllers
    IndexController.java
  /webapp/WEB-INF
    /views
    web.xml
    dispatcher-servlet.xml
```

## JSPファイルを作る

Communityエディションの場合、Springサポートがないため、ファイルの新規作成で`JSP/JSPX`が出てこない様子。 https://www.jetbrains.com/ja-jp/idea/features/editions_comparison_matrix.html

なので、普通に`File`を選んで、全部自作する。

```jsp:index.jsp
<%@ page import="org.example.controllers.IndexController" %>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Spring Test Page</title>
    </head>
    <body>
        <p>${someAttribute}</p>
    </body>
</html>

```


# Jettyで起動する

大人の都合でTomcatではなくJettyを使う。
IntelliJ IDEAのUltimate(有償版)であれば、Tomcatがデフォルトで組み込まれているらしい（？）が、Communityなのでどのみち使えない。
Jettyは事前にインストールしておく必要がないので楽。

http://zetcode.com/spring/jetty/ を参考に、pom.xmlに以下を足した。

```xml

   <packaging>war</packaging>
```
```xml
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
```
```xml
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.2</version>
            </plugin>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.14.v20181114</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
```

この状態で

```sh
mvn jetty:run
```

を実行し、`http://0.0.0.0:8080`にアクセスすると、無事にHelloWorldが表示される。

![スクリーンショット 2020-06-28 19.37.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299048/a00b227c-282a-6173-b10e-18b09c8a003d.png)


`maven-compiler-plugin`でソースとターゲットのバージョンを指定しない場合5になるらしく、エラーが起きてしまう。 http://orionb312.hatenablog.com/entry/2018/03/06/233734

```
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project spring-sample: Compilation failure: Compilation failure: 
[ERROR] ソース・オプション5は現在サポートされていません。7以降を使用してください。
[ERROR] ターゲット・オプション5は現在サポートされていません。7以降を使用してください。
```

# おわり

出来上がったものは以下。
https://github.com/sekikatsu36/spring-sample

とりあえず、Springが動くところは確認できた。
もうちょっとやりたいところ。

- WebPageではないAPIにしたい（Jerseyを使う？）
- デバッグできるようにしたい（今はブレークポイントで止まらない）
- PaaSやSaaSを使いたい