Controllerのメソッドの引数にRequestParamを羅列することなく、コードの見通しを良くするためにModelAttributeオブジェクトを使ってフォームパラメータを送受信する方法を紹介します。
新規プロジェクトの作成
Intellij IDEAでSpring Initializrを選択し新規プロジェクトを作成します。依存関係として以下を選択します。
- Spring Boot DevTools
- Lombok
- Spring Web
- Thymeleaf
フォームの内容を受け取るクラスの作成
フォームの入力内容を一つのJavaにまとめ、各入力値に相当するプロパティを定義します。これをフォームクラスと呼びます。
以下にフォームの内容を受け取るフォームクラスを作成します。
package com.example.springboo3samplemodelattribute;
import lombok.Data;
@Data
public class FormData {
private String name;
private String password;
private int gender;
private int blood;
private int[] categories;
private String note;
}
プロパティ名はフォームの部品と同じ名前を用います。
@Data
はLombokが提供するアノテーションです。@Data
を指定することで、getterとsetterが自動的に生成されます。Intellij IDEAのgetter/setter自動生成機能と異なり、クラスにコードは生成されません。getter/setter以外にも、デフォルトコンストラクタ、toString()
メソッドなども自動生成されます。
以下のようにFormDataのStructureにgetter/setterが追加されていることが確認できます。
Controllerの作成
Controllerを作成します。フォームの要素をFormData
クラスのgetterで取得します。register
メソッド引数に指定するオブジェクトがFormData
とModelAndView
の2種類だけになるので大分コードが整理されました。
@RestController
public class FormController {
@PostMapping("/register")
public ModelAndView register(
@ModelAttribute FormData formData,
ModelAndView mv
) {
StringBuilder sb = new StringBuilder();
sb.append("Name: " + formData.getName());
sb.append("Password: " + formData.getPassword());
sb.append("Gender: " + formData.getGender());
sb.append("Blood: " + formData.getBlood());
sb.append("Category: " + Arrays.toString(formData.getCategories()));
sb.append("Note: " + formData.getNote().replaceAll("\n",""));
mv.setViewName("result");
mv.addObject("userData", sb.toString());
return mv;
}
}
フォームクラスを使用しなかった場合のコードを比較のために以下に記載します。
@Controller
public class HelloController {
@PostMapping("/register")
public ModelAndView register(
@RequestParam("name") String name,
@RequestParam("password") String password,
@RequestParam("gender") int gender,
@RequestParam("blood") int blood,
@RequestParam("category") int[] categories,
@RequestParam("note") String note,
ModelAndView mv
) {
StringBuilder sb = new StringBuilder();
sb.append("Name: " + name);
sb.append("Password: " + password);
sb.append("Gender: " + gender);
sb.append("Blood: " + blood);
sb.append("Category: " + Arrays.toString(categories));
sb.append("Note: " + note.replaceAll("\n",""));
mv.setViewName("result");
mv.addObject("userData", sb.toString());
return mv;
}
}
入力フォームの作成
静的HTMLで以下のファイルを作成します。
このファイルはThymeleafテンプレートではなく、静的HTMLですので、保存先は
以下になります。
src/main/resources/static/form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>入力フォーム</title>
</head>
<body>
<form action="register" method="post">
<table>
<tr>
<td>Name</td>
<td>
<input type="text" name="name">
</td>
</tr>
<tr>
<td>Password</td>
<td>
<input type="password" name="password">
</td>
</tr>
<tr>
<td>Gender</td>
<td>
<input type="radio" name="gender" value="1">男性
<input type="radio" name="gender" value="2">女性
<input type="radio" name="gender" value="0">回答したくない
</td>
</tr>
<tr>
<td>血液型</td>
<td>
<select name="blood">
<option value="1">A型</option>
<option value="2">B型</option>
<option value="3">AB型</option>
<option value="4">O型</option>
</select>
</td>
</tr>
<tr>
<td>カテゴリ</td>
<td>
<input type="checkbox" name="category" value="1">金融
<input type="checkbox" name="category" value="2">製造業
<input type="checkbox" name="category" value="3">サービス業
<input type="checkbox" name="category" value="4">通信
<input type="checkbox" name="category" value="g">その他
</td>
</tr>
<tr>
<td>メモ</td>
<td>
<textarea name="note" rows="4" cols="90"></textarea>
</td>
</tr>
</table>
<input type="submit" value="送信">
</form>
</body>
</html>
結果表示用テンプレートの作成
以下にThyemeleafテンプレートファイルを作成します。
src/main/resources/templates/result.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Result</title>
</head>
<body>
<span th:text="${userData}"></span>
</body>
</html>
実行
それではブラウザからアクセスしてみます。
入力フォームに適当に値を入力して送信ボタンをクリックします。
結果が正しく表示されました。