Spring Bootで実行可能jarを作成する
実行可能jarを作成する
Spring Bootでは実行可能なjarを作成できます。
これはwarファイルをWebアプリケーションサーバにデプロイするといった面倒な作業を省き、java -jar
でWebアプリが起動できることを意味します。
実行可能jarの作り方は簡単です。 以下のコマンドを実行するだけです。
./mvnw clean package
以下のようなエラーが出たときはコンパイルのバージョンが異なっています。
$ ./mvnw clean package Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/maven/wrapper/MavenWrapperMain : Unsupported major.minor version 51.0 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637) at java.lang.ClassLoader.defineClass(ClassLoader.java:621) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Javaの対応表は以下の通り。
J2SE 8 = 52, J2SE 7 = 51, J2SE 6.0 = 50, J2SE 5.0 = 49, JDK 1.4 = 48, JDK 1.3 = 47, JDK 1.2 = 46, JDK 1.1 = 45
以下の記事が参考になります。 http://qiita.com/iwag@github/items/3f749010f0981195e2ba
java -version
で1.7以上を指定しても、mavenが見ているJavaが1.6だとエラーが出ます。
maven実行前にJAVA_HOMEを指定する必要があります。
$ JAVA_HOME=`/usr/libexec/java_home -v 1.8` ./mvnw clean package
これでjarを作成することができました。
[INFO] --- spring-boot-maven-plugin:1.4.3.RELEASE:repackage (default) @ demo --- [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 18.982 s [INFO] Finished at: 2017-01-02T11:59:45+09:00 [INFO] Final Memory: 29M/267M [INFO] ------------------------------------------------------------------------
targetディレクトリ以下にjarができています。
Spring Bootを使い始めるためのチュートリアル
Spring Bootは2013年に開発が始まり、2014年4月にバージョン1.0がリリースされました。 Spring Bootを使えば最初からさまざまな機能を利用することができます。
アプリケーションサーバにデプロイするという面倒な作業を省き、mainメソッドを実行するだけでWebアプリを実行できます。
Spring Bootを始める
まずは以下のURLに移動します。 https://start.spring.io/
次に、DependenciesのSearch for dependenciesで「Web」を入力してEnterを押します。
そしてGenerate Projectをクリックします。
ダウンロードされたプロジェクトを解凍して、Spring Tool Suiteに取り込みます。
Spring Tool Suiteでは、
File -> Import -> Existing Maven Projectsを選択し、Nextを押下。
先ほど解凍したフォルダを選択します。
取り込んだプロジェクトを実行するだけで、Webアプリケーションが起動します。
DemoApplication.javaをいじってみる
ダウンロードしたdemoを実行しても、初期状態のままではブラウザに何も表示されません。
Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Sun Jan 01 20:47:47 JST 2017 There was an unexpected error (type=Not Found, status=404). No message available
こんな感じのメッセージが出るだけです。
なぜなら、Controllerがないからです。 HTTP GETを受け取るようにしましょう。
package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class DemoApplication { @RequestMapping("/") String hello() { return "Hello Spring Boot!"; } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
Javaを修正した後に、localhost:8080にアクセスしてみます。
すると、
「Hello Spring Boot!」
と表示されます。
Spring Bootでテストコードを書く
Spring Initializerで生成したプロジェクトには、デフォルトでテストコードが含まれています。 たとえば、以下のようなコードを書いて、実行すると、上のコードをテストしてくれます。
package com.example; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.context.embedded.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.client.RestTemplate; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class DemoApplicationTests { RestTemplate restTemplate = new RestTemplate(); @LocalServerPort int port; @Test public void contextLoads() { assertThat(restTemplate.getForObject("http://localhost:" + port, String.class), is("Hello Spring Boot!")); } }
Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発
- 作者: 株式会社NTTデータ
- 出版社/メーカー: 翔泳社
- 発売日: 2016/07/21
- メディア: 大型本
- この商品を含むブログ (1件) を見る
Web開発環境を準備する
必要なツール
- Node.js
- Gulp
Gulpがやってくれること
GulpはSassやJSの圧縮などの作業を行ってくれる「タスクランナー」と呼ばれるツールのことです。 タスクランナーにはGulpの他に、GruntやBroccoliなどがあります。
Gulpがやってくれる作業は以下のようなものです。
package.json
package.jsonというファイルにはnodeでインストールできるモジュールが入っています。
{ "name": "src", "version": "1.0.0", "description": "", "main": "gulpfile.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "devDependencies": { "browser-sync": "^2.11.1", "gulp": "^3.9.0", "gulp-autoprefixer": "^3.1.0", "gulp-changed": "^1.3.0", "gulp-concat": "^2.6.0", "gulp-csso": "^1.0.1", "gulp-imagemin": "^2.4.0", "gulp-load-plugins": "^1.2.0", "gulp-rename": "^1.2.2", "gulp-sass": "^2.1.1", "gulp-sourcemaps": "^1.6.0", "gulp-uglify": "^1.5.1", "gulp-watch": "^4.3.9" } }
gulpfile.js
Gulpの動作はgulpfile.jsに定義されています。
基本となるgulpfile.jsは以下のようなものです。
var gulp = require('gulp'); var $ = require('gulp-load-plugins')(); var browserSync = require('browser-sync'); var paths = { "htmlSrc" : "./*.html", "scssSrc" : "./src/scss/**/*.scss", "jsSrc" : "./src/js/*.js", "jsLib" : "./src/js/lib/*.js", "imgSrc" : "./src/images/**", "rootDir" : "./dist/", "imgDir" : "./dist/images/", "jsDir" : "./dist/js/" } gulp.task('bs', function() { browserSync.init({ server: { baseDir: "./" }, notify : true, xip : false }); }); gulp.task('scss', function() { return gulp.src(paths.scssSrc) .pipe($.sourcemaps.init()) .pipe($.sass()).on('error', $.sass.logError) .pipe($.autoprefixer({ browsers: ['last 2 versions'] })) .pipe($.sourcemaps.write()) .pipe(gulp.dest(paths.rootDir + 'css')) .pipe($.rename({ suffix: '.min' })) .pipe($.csso()) .pipe(gulp.dest(paths.rootDir + 'css')) .pipe(browserSync.reload({ stream: true, once : true })); }); gulp.task('bs-reload', function() { browserSync.reload(); }); gulp.task('image', function() { return gulp.src(paths.imgSrc) .pipe($.changed(paths.imgDir)) .pipe($.imagemin({ optimizationLevel: 3 })) .pipe(gulp.dest(paths.imgDir)); }); gulp.task('js', function() { return gulp.src([paths.jsLib, paths.jsSrc]) .pipe($.uglify({preserveComments: 'license'})) .pipe($.concat('main.min.js', {newLine: '\n'}) ) .pipe(gulp.dest(paths.jsDir)); }); gulp.task('default', ['image', 'js', 'bs', 'scss', 'bs-reload'], function() { $.watch([paths.htmlSrc],function(e) { gulp.start("bs-reload") }); $.watch([paths.scssSrc],function(e) { gulp.start("scss") }); $.watch([paths.imgSrc],function(e) { gulp.start("image") }); $.watch([paths.jsSrc],function(e) { gulp.start("js") }); });
このgulpfile.jsがあるディレクトリで、gulp
を実行すると、gulpfile.jsの内容が実行されます。
Spring BootでBasic認証を導入するpom.xml定義
Spring Bootで Basic認証を導入するのは非常に簡単でした。
pom.xmlに以下の定義を追加します。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
なんとこれだけで、basic認証が実現できます。
パスワードは起動時のログに設定されますが、明示的に指定するにはapplication.propertiesに記載します。
security.user.name=demo security.user.password=demo security.basic.enabled=false
security.basic.enabled
はデフォルトで有効になるBasic認証を有効にするか無効にするかを設定します。
基本はtrueですが、falseにするとBasic認証を向こうにすることができます。
Spring Bootでデータベースにアクセスしてみる。
Spring BootではSpring JDBCが簡単に使えます。 DBアクセスが必要なアプリケーションも非常に簡単に作ることができます。 正直、拍子抜けするくらいに。
pom.xmlに以下を追記します。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency>
次に、DBのデータを突っ込むBeanクラスを作りましょう。
package com.example; import java.io.Serializable; public class Message implements Serializable { private String text; public String getText() { return text; } public void setText(String text) { this.text = text; } }
そして、JDBCとの接続クラスを作ります。
package com.example; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("messages") public class MessageController { @Autowired JdbcTemplate jdbcTemplate; final List<Message> messages = new CopyOnWriteArrayList<>(); @RequestMapping(method = RequestMethod.GET) public List<Message> getMessages() { return jdbcTemplate.query("SELECT text FROM messages ORDER BY id", (rs, i) -> { Message m = new Message(); m.setText(rs.getString("text")); return m; }); } @RequestMapping(method = RequestMethod.POST) public Message postMessages(@RequestBody Message message) { jdbcTemplate.update("INSERT INTO messages(text) VALUES (?)",message.getText()); return message; } }
これでソースの準備は完了です。
Spring Bootはデフォルトの挙動として、クラスパス直下にschema.sqlが存在すると、起動時にSQOファイルを実行します。 /src/main/resources以下にdbというソースフォルダを作りましょう。
普通のフォルダではなく、ソースフォルダを作ります。 そのdbソースフォルダの下に、schema.sqlファイルを作成します。
schema.sql
CREATE TABLE messages ( id INT PRIMARY KEY AUTO_INCREMENT, text VARCHAR(255) );
同じdbフォルダに、data.sqlを作ります。
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html
公式ドキュメントによると、起動時にdata.sqlに定義されているデータを挿入してくれます。
data.sql
INSERT INTO MESSAGES (text) VALUES('sample');
これでJavaを実行します。
http://localhost:8080/messages
にリクエストを飛ばすと、
json
[{"text":"sample"}]
というJSONが返ってきます。
Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発
- 作者: 株式会社NTTデータ
- 出版社/メーカー: 翔泳社
- 発売日: 2016/07/21
- メディア: 大型本
- この商品を含むブログ (1件) を見る
Spring BootでテンプレートエンジンThymeleafを使って画面表示
テンプレートエンジンとしてThymeleafを使ってみます。
まず、pom.xmlに以下のように依存性を追加します。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
次に、Controllerを作成します。
package com.example; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class HelloController { @RequestMapping("/hello") public String Hello(Model model) { model.addAttribute("hello", "Hello Thymeleaf World!"); return "hello"; } }
このControllerで返す「Hello Thymeleaf World」を表示させるテンプレートファイルを作成します。 場所は、
/src/main/resource/templates/hello.html
に作成します。
Spring Bootの自動設定では、TemplateResloverがビュー名につけるプレフィックスとサフィックスのデフォルト値は、それぞれ"classpath:/templates/"と".html"になるためです。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"></meta> <title>example</title> </head> <body> <p> <span th:text="${hello}"></span> </p> </body> </html>
これで、http://localhost:8080/hello
にリクエストをとばすと、
Hello Thymeleaf World!
と表示されます。
全てのJSPでタグライブラリを自動設定する
JSPのタグライブラリをいちいち全てのJSPファイルに書き込むのが面倒な人もいると思います。 全部に書く場合は書き漏れも心配です。
そのような人はweb.xmlに定義を追加しましょう。
<jsp-config> <jsp-property-group> <url-pattern>*.jsp</url-pattern> <page-encoding>UTF-8</page-encoding> <include-prelude>/WEB-INF/include.jsp</include-prelude> </jsp-property-group> </jsp-config>
この定義を追加して、/WEB-INF/include.jspを作ります。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
そうすると、最初にinclude.jspで定義した内容が読み込まれて設定されます。
http://otndnld.oracle.co.jp/document/products/wls/docs103/webapp/web_xml.html#wp1071166
jsp-config 要素は、Web アプリケーション内の JSP ファイルのグローバル コンフィグレーション情報を提供するために使用します。 2つの下位要素 taglib および jsp-property-group があります。
jsp-property-groupとは、複数のファイルをグループ化して、それらのファイルにグローバル プロパティ情報を提供できるようにするためのものです。 このように記述されたすべてのファイルは JSP ファイルと見なされます。
include-preludeというのは、JSPの先頭にインクルードするファイルのURIを指定します。JSPの先頭にincludeディレクティブを指定するのと同じ動作になります。
http://software.fujitsu.com/jp/manual/manualfiles/M090097/B1WS0331/03Z200/B0331-02-07-05-17.html