Spring BootでWARファイルを作成してTomcatへデプロイする方法
Spring Bootでwarを作成してTomcatへデプロイする方法です。
Spring Boot では、開発効率の向上のため、Tomcat が組み込まれております。そのため、jar ファイル単独で動作します。サーバーで jar をサービス登録し、Apache と連携すれば動きます。デプロイ不要で、クラウド時代にマッチした構成なのだと思います。しかし、本番環境は既に別の Tomcat があり、そっちで稼働させたいなんてニーズ多いんじゃないでしょうか。私のクライアントもこのような環境になっています。多くの企業がそういった状況にあるのではないかと思います。
別の Tomcat で動作させるには war ファイルを作成してデプロイする必要があります。
今回は Spring Bootでwarファイル作成から、既存Tomcatへのデプロイまで を紹介します。
開発中は Spring Boot 組み込み Tomcat を使って、テスト環境や本番環境は別 Tomcat にデプロイしたいって方のお役に立てればうれしいですね。
環境
- Spring Boot 1.4.1
- Thymeleaf 3.0.2
- Windows7
- Java8
- Eclipse 4.6 Neon
こちらのページを参考にサンプルアプリを作ってください。既にSpring Boot Webアプリがある場合は、読み飛ばして結構です。
Spring BootでWARを作成
まず、pom.xml の packaging を jar から war に変えます。
<packaging>war</packaging>
次に、下記の dependency を追加します。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
ポイントは scope を provided にすることです。Tomcat を外に追い出す感じですかね。
pom.xml ファイルを保存すると、下記のようなエラーが出ました。
動的 Web モジュール 3.1 は Java 1.7 またはそれ以降 を要求します。はて? Java は8だし、ビルドパスも Java 8 なのに??
実は Eclipse で Maven プロジェクトを作成した場合、デフォルトで JRE システムライブラリが 1.6 になります。[プロジェクト]-[プロパティ]-[ビルドパス]で 1.8 に変更しても、一旦解決したように見えて、またすぐに戻ってしまいます。
この場合、pom.xml で、ビルドする JDK を明示的に指定すれば解決できます。
下記を追記しましょう。
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
java.version を指定することで、maven.compiler.source と maven.compiler.target の指定が不要になります。failOnMissingWebXml は指定しなくても動作したので記述していません。
全体の 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>helloworldboot</groupId>
<artifactId>springbootapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>springbootapp</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.5</thymeleaf-layout-dialect.version>
<thymeleaf-extras-springsecurity4.version>3.0.2.RELEASE</thymeleaf-extras-springsecurity4.version>
<thymeleaf-extras-data-attribute.version>2.0.5</thymeleaf-extras-data-attribute.version>
<thymeleaf-extras-java8time.version>3.0.0.RELEASE</thymeleaf-extras-java8time.version>
</properties>
<build>
<finalName>springbootapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
最終的なファイル名は springbootapp.war になるよう、finalName を追記しています。
次に App クラスを変更します。
このクラスをエントリポイントとし、 SpringBootServletInitializer クラスの継承と、configure メソッドを override します。
package springbootapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
@SpringBootApplication
public class App extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(App.class);
}
}
pom.xml を右クリックで Maven clean install を実行しましょう。
war ファイルが出来上がります。
・・・と、ここでよくログを見てみると、「groovy-2.4.7.jarの読込みエラー」なるものが出ていました。
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ springbootapp ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to C:/Eclipse/4.6/workspace/springbootapp/target/classes
[WARNING] C:/Users/(ユーザー名)/.m2/repository/org/codehaus/groovy/groovy/2.4.7/groovy-2.4.7.jarの読込みエラーです。invalid LOC header (bad signature)
調べてみると、「invalid LOC header (bad signature)」は、ファイルが壊れている時に起こるエラーのようです。
・maven - spring error during build - Stack Overflow
なので Groovy 公式サイトからダウンロードして、groovy-2.4.7.jar を上書きします。
・The Groovy programming language - Download
上書きしたら Maven clean install を再実行しましょう。これをやらないと Tomcat のデプロイに失敗します。
エラーが出ていない方は、読み飛ばしてください。
Spring BootアプリをTomcatへデプロイ
さてさて、いよいよ Tomcat へデプロイしますよ。
Tomcat は Maven ビルド時に設定した Java のバージョンと同じであることが前提です。違っていると正しく動作しません。先ほど pom.xml の properties に java.version を 1.8 と追記したので、Tomcat も Java8 で動作させましょう。コマンドプロンプトから起動する場合、JAVA_HOME に依存しますので注意してください。
Eclipse から起動する場合は、Tomcat Plugin の追加が必要です。メニューのヘルプから Eclipse マーケットプレースを起動し、Tomcat Plugin と入力します。ここでは Eclipse Tomcat Plugin 9.1.2 をインストールしました。
target ディレクトリ配下に .war ファイルを Tomcat インストールディレクトリ配下の webapp ディレクトリにコピーします。Tomcat を起動すると、勝手に展開されて以下のように war ファイルと同じフォルダが出来上がります。
Tomcat 8 以上を使っていて Web アプリケーションマネージャからデプロイすると失敗する場合があります。その場合「Tomcat 8/8.5 Manager Appからのwarデプロイに失敗する」を参考にしてみてください。
URL は「http://ホスト名:ポート/アプリ名/*」となります。.jar での実行時と形式が変わるので注意しましょう。
ここでは http://localhost:8080/springbootapp/ へアクセスします。
おおお、表示されましたねー^^
まとめ
Spring Bootでwarを作成してTomcatへデプロイする方法を紹介しました。
「groovy-2.4.7.jarの読込みエラー」でちょっとハマりましたけど、手順さえしっかりしておけば、特に迷うことなく作業が進められましたね。
しかし web.xml なしで Tomcat にデプロイしたら Filter したい場合はどうするのよ?って声が聞こえてきそうですね。確かにエンコーディングやロギングなんかは Filter 実装というのが定番でしたからね。この辺りは次回に紹介したいと思います。
おつかれさまでした。