今日からは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を読んでおこうと思う。