Spring Boot でフォームの値を取得して操作
(2015.10.31 Yosemite)
Spring Boot プロジェクトを作成するところから、
フォームの値を取得して操作するまでを実行してみました。
Java のウェブアプリケーション作成は、ほとんど素人なので、
色々とおかしなところがあるかもしれません。
Mac Book Air (MBA) の初期設定メモ書き Part2 にて、
JDK と IntelliJ IDEA が導入済みです。
プロジェクトの雛形の作成
- Gradle のインストール
brew install gradle
- IntelliJ IDEA で Gradle プロジェクトの作成
IntelliJ IDEA を起動 -> Create New Project -> Gradle -> Next ->
GoupId: org.mygroup.webapp
ArtifactId: spring-boot-example1
Version: 0.0.1-SNAPSHOT
-> Next -> Next -> Next -> Finish
- build.gradle の編集
以下のように編集
group 'org.mygroup.webapp'
version '0.0.1-SNAPSHOT'
buildscript {
ext {
springBootVersion = '1.2.7.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath('io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE')
classpath('org.springframework:springloaded:1.2.1.RELEASE')
}
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'io.spring.dependency-management'
jar {
baseName = 'spring-boot-example1'
version = '0.0.1-SNAPSHOT'
}
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
task wrapper(type: Wrapper) {
gradleVersion = '2.8'
}
- リポジトリのアップデートと、build.gradle のリフレッシュ
初めてだと、IntelliJ IDEA の出すメッセージに従って、
リポジトリのアップデートと、build.gradle のリフレッシュが出来ましたが、
いつでもできるように方法を調べました。
- リポジトリのアップデート
IntelliJ IDEA メニュー -> Preferences (⌘,)
-> Build, Execution, Development
-> Build Tools -> Maven -> Repositories
-> URL: http://repo1.maven.org/maven2 を選択
-> Update ボタンをクリック
- build.gradle のリフレッシュ
IntelliJ IDEA ウィンドウの右端中央付近にある "Gradleアイコン" をクリック
(無いときは、左下端にある "ウィンドウの絵のようなアイコン" をクリック)
-> "Gradleアイコン" を押すと、Gradle Tool Window が開く
-> Gradle Tool Window 左上端にある水色のリフレッシュボタンを押す
- 雛形の作成
http://start.spring.io/ にアクセス
-> Gradle プロジェクト、Spring Boot 1.2.7 を選択
-> フォームを以下のように入力
Group: org.mygroup.webapp
Artifact: spring-boot-example1
-> Generate Project ボタンをクリック
-> ダウンロードされた zip ファイルを解凍
-> 中にある src フォルダを IntelliJ IDEA で作成したプロジェクトルートに移動
プロジェクトのディレクトリ構造
spring-boot-example1
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── spring-boot-example1.iml
└── src
├── main
│ ├── java
│ │ └── org
│ │ └── mygroup
│ │ └── webapp
│ │ └── SpringBootExample1Application.java
│ └── resources
│ └── application.properties
└── test
└── java
└── org
└── mygroup
└── webapp
└── SpringBootExample1ApplicationTests.java
HTML File の作成
Handling Form Submission を参考に、
フォームから値を受け取って、表示するサイトを作成
- index.html
/src/main/resources/templates フォルダを作成
-> そこに、まずは index という名前の HTML File を作成
(index.html は、フォームに入力された値を送信する役割)
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Index</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Form</h1>
<form action="#" th:action="@{/result}" th:object="${indexForm}" method="post">
<p>Id: <input type="text" th:field="*{id}" /></p>
<p>Message: <input type="text" th:field="*{content}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>
th:action="@{/result}"
がフォームのアクション指定
th:object="${indexForm}"
がフォームの内容が全て入る indexForm オブジェクト
th:field="*{id}"
が indexForm オブジェクトの id フィールド
th:field="*{content}"
が indexForm オブジェクトの content フィールド
Submit ボタンが押されると、"/result" にマッピングされたメソッドが呼ばれる。
そのメソッドは引数として、indexForm オブジェクトを受け取ることができる。
- result.html
続いて、/src/main/resources/templates に result という HTML File を作成
(result.html は、フォームに入力された値を表示する役割)
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Result</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Result</h1>
<p th:text="'id: ' + ${indexForm.id}" />
<p th:text="'content: ' + ${indexForm.content}" />
<a href="/">Submit another message</a>
</body>
</html>
${indexForm.id}
で、送られてきた indexForm オブジェクトの id フィールドを取得
${indexForm.content}
で、送られてきた indexForm オブジェクトの content フィールドを取得
Submit another message リンクで、"/" にマッピングされたメソッドが呼ばれる
Java Class の作成
- SpringBootExample1Application.java
org.mygroup.webapp パッケージには、以下のクラスが自動生成済み。
このクラスには、特に変更を加える必要はありませんでした。
package org.mygroup.webapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootExample1Application {
public static void main(String[] args) {
SpringApplication.run(SpringBootExample1Application.class, args);
}
}
- IndexFormController.java
同じ org.mygroup.webapp パッケージに
IndexFormController という Java Class を作成。
"/" でも、"/index" でも index.html が表示されるように、
どちらでも return "index";
としました。
複数の URL を、一つの html ファイルにマッピングするのに、
何かもっとちゃんとした書き方がありそうな気はします・・・
(2015.11.16 追記)
Multiple Spring @RequestMapping annotations によると、
@RequestMapping(value={"/", "/index"})
とすれば良かったみたいです
package org.mygroup.webapp;
import org.mygroup.webapp.model.IndexForm;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class IndexFormController {
@RequestMapping(value="/")
public String index1(Model model) {
model.addAttribute("indexForm", new IndexForm());
return "index";
}
@RequestMapping(value="/index")
public String index2(Model model) {
model.addAttribute("indexForm", new IndexForm());
return "index";
}
@RequestMapping(value="/result", method=RequestMethod.POST)
public String indexFormSubmit(@ModelAttribute IndexForm indexForm, Model model) {
if (indexForm.getId() == 1) {
indexForm.setContent("お前がナンバーワンだ!");
}
model.addAttribute("indexForm", indexForm);
return "result";
}
}
model.addAttribute("indexForm", new IndexForm())
として、
空のインスタンスをフォームにセットしないと、index.html を開くとエラーが発生。
Error during execution of processor 'org.thymeleaf.spring4.processor.attr.SpringInputGeneralFieldAttrProcessor' (index:10)
@RequestMapping(value="/result", method=RequestMethod.POST)
で、
"/result" とindexFormSubmit というメソッドをマッピング(メソッドが POST のときだけ)。
indexFormSubmit(@ModelAttribute IndexForm indexForm ...
で、
次に作成する IndexForm オブジェクトの indexForm インスタンスとしてフォームの値を取得。
- IndexForm.java
org.mygroup.webapp.model というパッケージを作成して、そこに、
IndexForm という Java Class を作成。
フォームから送られてきた indexForm の内容を格納するクラス。
package org.mygroup.webapp.model;
public class IndexForm {
private long id;
private String content;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
gradle bootRun
IntelliJ IDEA の Terminal から、gradle bootRun
を実行。
適当なブラウザで localhost:8080
としてサイトに接続し、動作確認。
その他
/src/main/resources/application.properties にて、
ポートの変更や、ホットデプロイのための設定が出来る。
server.port=8080
spring.thymeleaf.cache=false
GitHub に投稿
Mac Book Air (MBA) の初期設定メモ書き Part2 にて、
GitHub に接続できる状態になっています。
GitHub にて、spring-boot-example1 というリポジトリを作成
-> プロジェクトルートにて vim .gitignore
として、以下のように編集
.DS_Store
.gradle
.idea
build*
gradle*
*.iml
settings*
続いて、以下を実行
git init
git add .
git commit -m 'spring boot example1: handling form submission'
git remote add origin github:/username/spring-boot-example1.git
git push -u origin master