今日からはSpring Boot Reference Guideをつまみ食い的に読んでいく。
なにはなくとも、まずはHot swappingだろうと思って、これを調べた。ホットスワップとは、毎回毎回アプリを再起動しなくてもよくするための仕組みだ。
build.gradleのbuildscriptブロックに、以下を追加した。IntellJで開発しているので、ideaプラグインも入れてある。
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.1.RELEASE")
classpath 'org.springframework:springloaded:1.2.0.RELEASE'
}
}
apply plugin: 'idea'
idea {
module {
inheritOutputDirs = false
outputDir = file("$buildDir/classes/main/")
}
}
その後、HelloControllerを編集して/fooのマッピングを追加。
package sample;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/")
String index() {
return "Hello World!";
}
@RequestMapping("/foo")
String foo() {
return "Hello Foo!";
}
}
その後、gradle bootRunを実行(spring-bootプラグイン入れてること)。http://localhost:8080/fooにアクセスしてみたら、Hello Foo!と表示される。そのあと、Hello Foo!!!を返すようにHelloController.javaを編集し、またhttp://localhost:8080/fooにアクセスしたら表示が更新され…ない…!!!
原因がわからんなーとtwitterで呟いていたところ、@zephiransasさんに教えてもらった。原因は、HelloController.javaを更新するだけじゃなくて、HelloController.classを更新しないといけないので、再ビルドしないといけない、ということだった。な、なるほど…。RailsやPHPに慣れすぎた自分には全く思いつかない発想だった。Spring Boot自体の再起動が必要ない分だけマシ。Javaのコンパイルは速いから大丈夫。ということのようである。肝に銘じておこう。
サンプルコードを読む
The ‘Spring Web MVC framework’を読んでいこうとしたのだが、結局はspring.io/guideをやってみろ、みたいな感じに思えたので、そっちでSpring MVCでよさそうなのを探すことにした。
Serving Web Content with Spring MVCをやってみる
やはりhtmlを出力できないと色々と困るので、まずはテンプレートエンジンを使う方法を調べようと思った。ガイドの中だとおそらくこれだろう。テンプレートエンジンとしてThymeleafを使っている模様。Javaのテンプレートエンジンについては全然知らないので、まずはこれにしてみようと思う。
build.gradleを編集する
spring-boot-starter-thymeleafをdependenciesプロックに追加するようだ。
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.1.RELEASE")
classpath 'org.springframework:springloaded:1.2.0.RELEASE'
}
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'spring-boot'
idea {
module {
inheritOutputDirs = false
outputDir = file("$buildDir/classes/main/")
}
}
jar {
baseName = 'spring-boot-practice'
version = '0.1.0'
}
sourceCompatibility = 1.8
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
// compile("org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE")
// compile("org.springframework.boot:spring-boot-starter-actuator:1.2.1.RELEASE")
compile("org.springframework.boot:spring-boot-starter-thymeleaf:1.2.1.RELEASE")
testCompile("org.springframework.boot:spring-boot-starter-test:1.2.1.RELEASE")
}
sourceSets {
main {
java
}
test {
java
}
}
これでbuildしようとしたら、テストのところでThymeleafのテンプレート置き場がないと言われて落ちたので、ディレクトリsrc/main/resources/templatesを作った。
GreetingControllerを作成する
次に、テンプレートを読み込んで出力するためのControllerとしてGreetingControllerを作成した。
/greetingにマッピングされる。戻り値でテンプレートの場所を指定するようだ。ここで言えば、return “greeting”である。modelに、テンプレートに渡したい変数をaddAttributeで追加する模様。
package sample;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class GreetingController {
@RequestMapping("/greeting")
public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
return "greeting";
}
}
@RequestParamアノテーションは、変数とパラメータをバインディングするために使うみたいだ。
src/main/resources/templates/greeting.htmlを作成する
呼び出されるテンプレートを作る。
html xmlns:thでthymeleafの定義をロードしてるっぽい。
そして、pタグ内の要素th:textで変数を展開しているみたいだ。nameは、GreetingControllerでmodel.addAttributeで渡されたものが入る。
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Hello, ' + ${name} + '!'" />
</body>
</html>
起動する
Gradle taskのbootRunを実行してSpring Bootを起動する。
gradle bootRun
http://localhost:8080/greeting にアクセスすると、Hello World!と表示される。
http://localhost:8080/greeting?name=Okayama として、パラメータを渡すと、Hello Okayama!と表示された。
とりあえず成功した模様。
本日はここまでとして、あとはUnderstanding View Templatesを読んでおこうと思う。
