Spring Bootで作ったRESTfulなAPIをTomcat8にデプロイしてみる

久々の投稿。今回はSpring Boot製アプリをTomcat8にデプロイ、起動してみたお話です
所々間違ったことを言っているかもしれないので、コメントで教えてくれると助かります
あと、今回の記事で扱うTomcatのバージョンは**8**です。**9**ではないのでご注意ください
また、Apache2との連携(連動?)はせず、Tomcat単体での運用になります

余談だけど、はてなブログに書いたサーバー関連のメモ記事も、こっちに書いた方がいいのかなぁ

## 動作環境
- Linux mint 19.1(Tomcat8実行マシンOS)
- JDK8
- Spring Boot 2.2.0.RELEASE
- Maven

## パッケージのインストール
`sudo apt update && sudo apt install -y tomcat8`
updateする必要はないかもしれないけど一応。パッケージはこれだけで大丈夫なはず
(別途Apacheと連携させたいとかそういう場合はApache2もインストールが必要かも)

## Tomcatの設定
設定ファイルは`/var/lib/tomcat8/conf`以下にあります
ポートの設定とかデプロイディレクトリとかの設定は`server.xml`に記述しますが、今回の記事ではコンテキストパスの設定も同ファイルで行ってしまいます
(本来ならcontext.xmlでやるのだろうけど...)

### ポートの設定

```
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
               ↓
<Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
```

ほかの記事とかサイトを見ていると別のConnectorの方を書き換えているけど、僕の環境では上記の様に変更し**8081**にアクセスするとちゃんと適用できていたので大丈夫だと思いますが、間違っていたら教えてください。

### コンテキストパスの設定

```
<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
       <!--  Sampleアプリのパス設定  -->
       <Context path="/gn5rapl/sample/api/" docBase="sample-api.war" />
</Host>
```

~~1つわからないんですが、なんでコンテキスパスを設定した後にリロードすると、**gn5rapl#sample#api**っていうディレクトリが作られるのに、warのfinalNameを**gn5rapl#sample#api**にしてパッケージング、docBaseに**gn5r#sample#api(.war)**を直接指定しても動かないんですかね？心優しい人教えてください...
そういうのもあって、今回の例では**sample-api.war**という名前でパッケージングしています。後ほどpomの記述も紹介します~~

コンテキストパスの設定を初期設定のままtomcat8が起動してる状態で、gn5rapl#sample#api.warでwebappディレクトリへデプロイ、自動展開したのを確認後、少し待った後に**IPアドレス:ポート/gn5rapl/sample/api/swagger-ui.html**をブラウザで確認してみると動いているのを確認しました。下手にコンテキストを弄らないほうが良さそう...[^2]

## Spring Bootアプリの設定
順番が逆かもしれませんが、Spring Bootアプリの設定になります
2019年10月28日(日)現在では、Spring Bootアプリの新規作成の段階で**ServletInitializer.class**が生成されており、pom.xmlにも**spring-boot-starter-tomcat**が追加されています
無い場合は以下を参考にクラスを作成、またはApplicationクラスに継承させます

```java:ServletInitializer.java
public class ServletInitializer extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(SampleApiApplication.class);//適宜、Applicationクラス名を変更してください
	}
}
```

```xml:pom.xml
　　<groupId>gn5r.gn5rapl</groupId>
　　<artifactId>sample</artifactId>
　　<version>0.0.1-SNAPSHOT</version>
    <!-- packagingをwarにする -->
　　<packaging>war</packaging>
　　<name>Sample-api</name>
　　<description>Qiita投稿用サンプルAPIプロジェクト</description>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-tomcat</artifactId>
  <scope>provided</scope>
</dependency>

<build>
  <finalName>sample-api</finalName> <!-- ここで設定した名前.warになる -->
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
</build>
```

### Spring Bootアプリをパッケージング&&デプロイ
EclipseやStSなら実行→Maven cleanとMavenビルドのゴールを`package`にして実行
コマンドなら`mvn clean package`を実行します
するとtargetディレクトリに**sample-api.war**が生成されているのでscpなどでサーバマシンへファイルを送信します
(/var/libはroot権限じゃないとファイル転送できないと思うので、$HOME/Documentsに配置しました)

`sudo cp $HOME/Documents/sample-api.war /var/lib/tomcat8/webapp `
mvでもいいかもしれないけど、コピーにしてます

Tomcatの設定ファイルを弄っているので再起動する必要があるので以下を実行
`sudo systemctl restart tomcat8`

## 実行例
![swagger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230050/49577196-619a-18af-4ecf-98714d9b2a8f.png)

Sample-apiにSwaggerを導入させているので、動作確認も兼ねて表示テスト
IPアドレスをHostsファイルで弄っているので**gn5r.tomcat.jp**は各自のサーバーマシンのIPアドレスなどに変更して下さい

後ほど今回紹介したSpring Bootアプリを[GitHub(リンクになっています)](https://github.com/gn5r/springboot-tomcat)に置く予定なので、そちらも参考程度にしてみてください[^1]

[^1]: GitHubにリポジトリを作成、コミットしました
[^2]: 2020/01/20(月) 素のtomcat8で動かしたらできたので訂正しました