Spring Bootのウェブアプリケーションのサンプル。
単純に画面をひとつ表示するサンプルを作ってみる。(Spring Boot 1.5.6)
Spring Initializr(テンプレートとしてThymeleafを使用。DevToolsも入れておく)を使ってソース一式を生成し、そこに必要なソースを追加していく。
build.gradleは以下のようになる。
buildscript {
ext {
springBootVersion = '1.5.6.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
runtime('org.springframework.boot:spring-boot-devtools')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
ダウンロードしてきたdemoアプリケーションにはhtmlファイルが無いので、自分で作成する。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Hello Thymeleaf</title> </head> <body> <h1>Hello Thymeleaf</h1> </body> </html>
Thymeleafを使う場合、テンプレートファイルは普通のhtmlファイルとほぼ同じ。
ブラウザーから要求されたURIに対する処理を記述するのはControllerクラス。
package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping(path = "/hello")
public String hello() {
return "hello";
}
}
Controllerクラスには、@Controllerアノテーションを付ける。
URIの処理をするメソッドには@RequestMappingアノテーションで処理対象URIのバスを指定する。
パスが「/hello」の場合、ブラウザーから「http://ホスト名:8080/hello」でアクセスされたときに呼ばれることになる。
メソッド名は何でもいい。
メソッドの戻り値の型をStringにしておくと、そこで返す値はhtmlファイルを指定した事になる。
つまり「hello」を返すとhello.htmlがブラウザーに返されることになる。
(もしhtmlファイルがtemplates/hoge/zzz.htmlなのであれば、それを示すメソッドの戻り値は「hoge/zzz」になる)
STSを使っている場合、パッケージエクスプローラー上でDemoApplication.javaを右クリックして「Run
As」→「Spring Boot App」を選択すれば、ウェブアプリケーションが起動する。
通常のEclipseの場合でも普通にDemoApplicationを実行すればウェブアプリケーションが起動する。
ブラウザーから「http://localhost:8080/hello」を呼び出すと、HelloControllerが動いてhello.htmlが表示される(はず)。
コンソール上の停止ボタン(赤い四角いやつ)を押すとウェブアプリケーションは終了する。
Controller上で現在時刻を取得し、htmlで出力(画面に表示)してみる。
package com.example.demo; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss zzz");
@RequestMapping(path = "/hello")
public String hello(Model model) {
model.addAttribute("date", ZonedDateTime.now().format(FORMATTER));
return "hello";
}
}
メソッドの引数にModelを追加する。
このModelにaddAttributeすると、その値がhtmlで取得できる。
ちなみにDateTimeFormatterはMTセーフなので、Conrollerクラスのstaticフィールドで保持してメソッド内で使っても問題ない。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Hello Thymeleaf</title>
</head>
<body>
<h1>Hello Thymeleaf</h1>
<p>時刻: <span th:text="${date}">2017/08/26 12:34:56 JST</span></p>
</body>
</html>
htmlファイル上は「${名前}」でConrollerでModelにセットした値が取得できるのだが、それを指定する場所が独特。th:text属性に書く。
th:text属性の値は、実行時にはタグのボディー部に展開される。(元々ボディー部に書かれていた文は上書きされて消える)
つまりテンプレート上の「<span th:text="hoge">zzz</span>」は実行時には「<span>hoge</span>」になる。
(Thymeleafのこういう仕組みにより、テンプレートのhtmlファイルを直接ブラウザーで表示して、どう表示されるかを確認することが出来る(この場合にはタグのボディー部に書かれている内容が表示され、th:textはブラウザーが解釈できない属性なので無視される))
画面(htmlのform)で入力された値をControllerで取得してみる。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Hello Thymeleaf</title>
</head>
<body>
<h1>Hello Thymeleaf</h1>
<p>時刻: <span th:text="${date}">2017/08/26 12:34.56 JST</span></p>
<form action="#" th:action="@{/hello-submit}" method="post">
<p><input type="text" name="foo" /></p>
<p><input type="submit" value="submit"/></p>
</form>
</body>
</html>
formのinputは普通のHTML。
th:action属性でsubmitボタンが押された際のURIを指定する。
「@{ }」はThymeleafでURIを扱う際に付けるものらしい。
package com.example.demo;
〜 import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
〜
@RequestMapping(path = "/hello-submit")
public String helloSubmit(@ModelAttribute("foo") String foo, Model model) {
model.addAttribute("date", foo);
return "hello";
}
}
HttpRequestのパラメーターは、Controllerのメソッドの引数に@ModelAttributeアノテーションを付けるだけで受け取れる。
(@RequestParamアノテーションでもいいし、HttpServletRequestでrequest自体を受け取ることも出来なくはない)