7月10日

バリデーションの利用

バリデーション用に新しいプロジェクトを作成する。

プロジェクトの作成と初期設定

プロジェクト名: Memo
テンプレート: Simple Spring Web Maven

プロジェクトを作成したら、以下を実行。

  1. [Maven]-[プロジェクトの更新]
  2. [実行]-[maven install]

文字化け対策のために、web.xml を編集。
最後の <web-app> タグの手前に以下の内容を追加。
src/main/webapp/WEB-INF/web.xml

	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

使用するパッケージ名を mvc-config.xml に設定。
src/main/webapp/WEB-INF/mvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="jp.abc"/>


    <mvc:annotation-driven />

	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	        <!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
	        <property name="prefix" value="/WEB-INF/view/"/>
	        <property name="suffix" value=".jsp"/>
	</bean>

</beans>

サーバータブの Tomcat7 サーバーに Memo プロジェクトを追加して Tomcat7 サーバーを再起動。
http://localhost:8080/Memo/ にアクセスすれば、click to enter が表示される。

FormModelの作成

javaリソースの src/java/main を右クリックし、クラスを新規作成する。
パッケージ名: jp.abc
クラス名; FormModel

FormModel.java

package jp.abc;

import java.util.Date;

public class FormModel {
	private String item;
	private Integer price;
	private Date buydate;
	private String memo;
	public String getItem() {
		return item;
	}
	public void setItem(String item) {
		this.item = item;
	}
	public Integer getPrice() {
		return price;
	}
	public void setPrice(Integer price) {
		this.price = price;
	}
	public Date getBuydate() {
		return buydate;
	}
	public void setBuydate(Date buydate) {
		this.buydate = buydate;
	}
	public String getMemo() {
		return memo;
	}
	public void setMemo(String memo) {
		this.memo = memo;
	}
}

ビューテンプレートの変更

showMessage.jsp を以下のように変更する。

<!DOCTYPE html>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
	<head>
		<meta charset="utf-8">
		<title>${title}</title>
		<style type="text/css">
		h1 { font-size: 16pt;background-color: #ccccff;padding:3px; }
		p { color: #000066; }
		</style>
	</head>
	<body>
		<h1>${title}</h1>
		<p>${message}</p>
		<table>
		<form:form modelAttribute="formModel">
			<tr>
				<td><form:label path="item">商品名</form:label></td>
				<td><form:input path="item" size="20" /></td>
			</tr>
			<tr>
				<td><form:label path="price">金額</form:label></td>
				<td><form:input path="price" size="20" /></td>
			</tr>
			<tr>
				<td><form:label path="memo">メモ</form:label></td>
				<td><form:textarea path="memo" cols="20" rows="5" /></td>
			</tr>
			<tr><td><input type="submit"></td></tr>
		</form:form>
		</table>
		<hr />
		<c:if test="${datalist != null}" >
		<table border="1">
			<tr><th>商品名</th><th>価格</th></tr>
			<c:forEach var="obj" items="${datalist}" varStatus="status">
				<tr>
					<td>${obj.item}</td>
					<td>${obj.price}</td>
				</tr>
			</c:forEach>
		</table>
		</c:if>
	</body>
</html>

コントローラを作成する

買い物メモのコントローラを作成する。
テキストでは MyAppController を再利用しているが、ここでは新しく MemoController を作成する。
※開発する際に、名前は重要!

Javaリソースの src/java/main の下にある jp.abc パッケージを右クリックして [新規]-[クラス] を選択。

名前: MemoController

まずは、GET メソッドに対応する部分だけ入力する。

MemoController.java

package jp.abc;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MemoController {
	private List<FormModel> buylist = new ArrayList<FormModel>();

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String list(Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "買い物メモです。");
		FormModel fm = new FormModel();
		model.addAttribute("formModel", fm);
		model.addAttribute("datalist", buylist);
		return "showMessage";
	}
}

http://localhost:8080/Memo/list にアクセスする。
買い物メモの画面が表示されればOK。

次に POST メソッドに対応する部分を実装する。

MemoController.java

	@RequestMapping(value = "/list", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, BindingResult result, Model model) {
		buylist.add(formModel);
		model.addAttribute("title", "Sample");
		String res = "<ol>";
		res += "<li>" + formModel.getItem() + "</li>";
		res += "<li>" + formModel.getPrice() + "</li>";
		res += "<li>" + formModel.getMemo() + "</li>";
		res += "<li>" + Calendar.getInstance().getTime() + "</li>";
		res += "</ol>";
		res += "<p>" + buylist.size() + "</p>";
		model.addAttribute("message", res);
		model.addAttribute("datalist", buylist);
		model.addAttribute("formModel", new FormModel());
		return "showMessage";
	}

バリデーション用ライブラリをロードする

パッケージエクスプローラで、Memoプロジェクトの一番下にあるファイル pom.xml を開く。
エディタの下にある「pom.xml」タブを選択する。
ファイルの最後の <dependencies> の手前に以下の内容を追加する。

pom.xml

		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.0.1.Final</version>
		</dependency>
	</dependencies>
</project>

保存すると、自動的にプロジェクトがビルドされ、ライブラリをダウンロードしてくれる。

JSPの変更

showMessage.jsp にエラーメッセージを表示するためのタグを追加する。

showMessage.jsp

		<form:form modelAttribute="formModel">
			<tr><td></td><td><form:errors path="*" element="div" /></td></tr>
			<tr>
				<td><form:label path="item">商品名</form:label></td>
				<td><form:input path="item" size="20" /></td>
			</tr>

コントローラの変更

GETメソッドはバリデーションは関係なので、POSTメソッドを処理するメソッドを変更する。

まず、バリデーションの対象となる最初の引数 FormModel に @Valid アノテーションを追加する。

MemoController.java

	@RequestMapping(value = "/list", method = RequestMethod.POST)
	public String form(@Valid @ModelAttribute FormModel formModel, BindingResult result, Model model) {

エラーがあったときには、異なるタイトルとメッセージを表示するように変更する。
判断は、BindingResult#hasErrors()メソッドを使用する。
MemoController.java

	@RequestMapping(value = "/list", method = RequestMethod.POST)
	public String form(@Valid @ModelAttribute FormModel formModel, BindingResult result, Model model) {
		if (result.hasErrors()) {
			model.addAttribute("title", "Sample [ERROR]");
			model.addAttribute("message", "値を再チェックしてください");
		} else {
			buylist.add(formModel);
			model.addAttribute("title", "送信内容");
			String res = "<ol>";
			res += "<li>" + formModel.getItem() + "</li>";
			res += "<li>" + formModel.getPrice() + "</li>";
			res += "<li>" + formModel.getMemo() + "</li>";
			res += "<li>" + Calendar.getInstance().getTime() + "</li>";
			res += "</ol>";
			res += "<p>" + buylist.size() + "</p>";
			model.addAttribute("message", res);
			model.addAttribute("formModel", new FormModel());
		}
		model.addAttribute("datalist", buylist);
		return "showMessage";
	}

エラーメッセージのカスタマイズ

エラーメッセージを変更するには、アノテーションに message 引数を追加するのが簡単。

FormModel.java

public class FormModel {
	@NotEmpty(message="商品名は必須です。")
	private String item;
	@Min(value=0, message="{value}以上の値が必要です。")
	private Integer price;
	private Date buydate;
	private String memo;

個別にメッセージを表示する

現状では1箇所にまとめてエラーメッセージを表示しているが、これを入力フィールド毎に変更できる。
<form:errors> タグの path 属性の * を、それぞれの変数名で指定すればよい。

showMessage.jsp

		<form:form modelAttribute="formModel">
			<tr>
				<td><form:label path="item">商品名</form:label></td>
				<td><form:input path="item" size="20" />
				<form:errors path="item" cssStyle="color:red" /></td>
			</tr>
			<tr>
				<td><form:label path="price">金額</form:label></td>
				<td><form:input path="price" size="20" />
				<form:errors path="price" cssStyle="color:red" /></td>
			</tr>
			<tr>
				<td><form:label path="memo">メモ</form:label></td>
				<td><form:textarea path="memo" cols="20" rows="5" />
				<form:errors path="memo" cssStyle="color:red" /></td>
			</tr>
			<tr><td><input type="submit"></td></tr>
		</form:form>

7月6日

フォームを使いこなす(続き)

複数のチェックボックスをまとめて作る

前回は複数のチェックボックスをまとめて作成するところまで作ったが、クエリ送信でエラーが発生していた。

エラーメッセージでは items must not be null と表示されていることから、${checkItems} が null であると推測できる。

コントローラで値を設定するように修正する。

MyAppController.java

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		model.addAttribute("formModel", formModel);
		model.addAttribute("checkItems", getList());
		return "showMessage";
	}

チェックされた要素をメッセージに追加する。

MyAppController.java

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		String[] selected = formModel.getChecks();
		res = res + "<ol>";
		for (String sel : selected) {
			res += "<li>" + sel + "</li>";
		}
		res += "</ol>";
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		model.addAttribute("formModel", formModel);
		model.addAttribute("checkItems", getList());
		return "showMessage";
	}

ラベルと値を設定する

チェックボックスのラベルと値を設定するために、クラスを追加する。
javaリソースの下の src/main/java にある jp.abc パッケージを右クリックし、[新規]-[クラス]を選択する。
新規クラスのダイアログで名前に ListDataModel と入力し「完了」をクリック。
テキスト p.214 のコードを記述する。

ListDataModel.java

package jp.abc;

public class ListDataModel {
	private String label;
	private String data;
	public String getLabel() {
		return label;
	}
	public void setLabel(String label) {
		this.label = label;
	}
	public String getData() {
		return data;
	}
	public void setData(String data) {
		this.data = data;
	}
	public ListDataModel(String label, String data) {
		this.label = label;
		this.data = data;
	}
}

JSPの <form:checkboxes> の内部を変更する。

				<tr><td>
					<form:checkboxes items="${checkItems}" path="checks"
					itemLabel="label" itemValue="data" delimiter=" "/>
				</td></tr>

MyAppControllerでは、ListDataModel を格納した List を作るように getList() を修正する。

MyAppController.java

package jp.abc;

import java.util.ArrayList;
import java.util.List;

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 MyAppController {

	private List<ListDataModel> getList() {
		List<ListDataModel> list = new ArrayList<ListDataModel>();
		list.add(new ListDataModel("まっく", "Mac OS X"));
		list.add(new ListDataModel("うぃんどうず", "Windows"));
		list.add(new ListDataModel("りなくす", "Linux"));
		return list;
	}

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		fm.setCheck1(true);
		fm.setChecks(new String[]{"Windows"});
		model.addAttribute("formModel", fm);
		model.addAttribute("checkItems", getList());
		return "showMessage";
	}

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		String[] selected = formModel.getChecks();
		res = res + "<ol>";
		for (String sel : selected) {
			res += "<li>" + sel + "</li>";
		}
		res += "</ol>";
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		model.addAttribute("formModel", formModel);
		model.addAttribute("checkItems", getList());
		return "showMessage";
	}
}

ラジオボタンの利用

ラジオボタンは、<form:radiobutton> タグを使用する。

ラジオボタンのために、FormModel に radio1 を追加する。

FormModel.java

package jp.abc;

public class FormModel {
	private String input1;
	private String pass1;
	private String area1;
	private boolean check1;
	private String[] checks;
	private String radio1;

	public String getInput1() {
		return input1;
	}
	public void setInput1(String input1) {
		this.input1 = input1;
	}
	public String getPass1() {
		return pass1;
	}
	public void setPass1(String pass1) {
		this.pass1 = pass1;
	}
	public String getArea1() {
		return area1;
	}
	public void setArea1(String area1) {
		this.area1 = area1;
	}
	public boolean isCheck1() {
		return check1;
	}
	public void setCheck1(boolean check1) {
		this.check1 = check1;
	}
	public String[] getChecks() {
		return checks;
	}
	public void setChecks(String[] checks) {
		this.checks = checks;
	}
	public String getRadio1() {
		return radio1;
	}
	public void setRadio1(String radio1) {
		this.radio1 = radio1;
	}
}

JSP にラジオボタンのタグを追加する。

			<form:form modelAttribute="formModel">
				<tr><td>input1:<form:input path="input1"/></td></tr>
				<tr><td>pass1:<form:password path="pass1" showPassword="on"/></td></tr>
				<tr><td>area1:<form:textarea path="area1" cols="40" rows="3"></form:textarea></td></tr>
				<tr><td><form:checkbox path="check1" label="checkbox 1"/></td></tr>
				<tr><td>
					<form:checkboxes items="${checkItems}" path="checks"
					itemLabel="label" itemValue="data" delimiter=" "/>
				</td></tr>
				<tr><td><form:radiobutton path="radio1" name="radio1"
					label="男性" value="male"/>
					<form:radiobutton path="radio1" name="radio1"
					label="女性" value="female"/>
				<tr><td><input type="submit" ></td></tr>
			</form:form>

GETメソッドを処理する helo() メソッドでは、1行だけ追加する。

MyAppController.java

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		fm.setCheck1(true);
		fm.setChecks(new String[]{"Windows"});
		fm.setRadio1("male");
		model.addAttribute("formModel", fm);
		model.addAttribute("checkItems", getList());
		return "showMessage";
	}

POSTメソッドを処理する form() メソッドでも1行だけの追加。

MyAppController.java

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		String[] selected = formModel.getChecks();
		res = res + "<ol>";
		for (String sel : selected) {
			res += "<li>" + sel + "</li>";
		}
		res += "</ol>";
		res += "selected: " + formModel.getRadio1();
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		model.addAttribute("formModel", formModel);
		model.addAttribute("checkItems", getList());
		return "showMessage";
	}

ラジオボタンをまとめて作成する

複数のラジオボタンをまとめて作成するには、 <form:radiobuttons> タグを使用する。

まずは複数のラジオボタン用に、FormModel に radio2 を追加し、getter/setter を用意する。
FormModel.java

package jp.abc;

public class FormModel {
	private String input1;
	private String pass1;
	private String area1;
	private boolean check1;
	private String[] checks;
	private String radio1;
	private String radio2;

	public String getInput1() {
		return input1;
	}
	public void setInput1(String input1) {
		this.input1 = input1;
	}
	public String getPass1() {
		return pass1;
	}
	public void setPass1(String pass1) {
		this.pass1 = pass1;
	}
	public String getArea1() {
		return area1;
	}
	public void setArea1(String area1) {
		this.area1 = area1;
	}
	public boolean isCheck1() {
		return check1;
	}
	public void setCheck1(boolean check1) {
		this.check1 = check1;
	}
	public String[] getChecks() {
		return checks;
	}
	public void setChecks(String[] checks) {
		this.checks = checks;
	}
	public String getRadio1() {
		return radio1;
	}
	public void setRadio1(String radio1) {
		this.radio1 = radio1;
	}
	public String getRadio2() {
		return radio2;
	}
	public void setRadio2(String radio2) {
		this.radio2 = radio2;
	}
}

JSP に、複数のラジオボタンを表示するタグを追加する。

showMessage.jsp

				<tr><td><form:radiobutton path="radio1" name="radio1"
					label="男性" value="male"/>
					<form:radiobutton path="radio1" name="radio1"
					label="女性" value="female"/>
				</td></tr>
				<tr><td><form:radiobuttons path="radio2" name="radio2"
						items="${radiolist}" itemLabel="label" itemValue="data"
						delimiter=" " />
				</td></tr>
				<tr><td><input type="submit" ></td></tr>

GETメソッドを処理する helo() メソッドでは、FormModel の値を設定し、radiolist の名前で ListDataModel の List を渡してやる。

MyController.java

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		fm.setCheck1(true);
		fm.setChecks(new String[]{"Windows"});
		fm.setRadio1("male");
		fm.setRadio2("Linux");
		model.addAttribute("formModel", fm);
		model.addAttribute("checkItems", getList());
		model.addAttribute("radiolist", getList());
		return "showMessage";
	}

POST メソッドを処理する form() メソッドでは、選択された値を表示する1行の追加と、radiolist の名前で ListDataModel の List を渡してやる1行の追加のみ。

MyAppController.jav

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		String[] selected = formModel.getChecks();
		res = res + "<ol>";
		for (String sel : selected) {
			res += "<li>" + sel + "</li>";
		}
		res += "</ol>";
		res += "<br />selected: " + formModel.getRadio1();
		res += "<br />selected: " + formModel.getRadio2();
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		model.addAttribute("formModel", formModel);
		model.addAttribute("checkItems", getList());
		model.addAttribute("radiolist", getList());
		return "showMessage";
	}

SELECTによる選択リストの作成

複数項目をリスト表示する <select>タグは、<form:select> タグで作成できる。

まず、FormModel に select 用のメンバーを用意する。

FormModel.java

package jp.abc;

public class FormModel {
	private String input1;
	private String pass1;
	private String area1;
	private boolean check1;
	private String[] checks;
	private String radio1;
	private String radio2;
	private String select1;

	public String getInput1() {
		return input1;
	}
	public void setInput1(String input1) {
		this.input1 = input1;
	}
	public String getPass1() {
		return pass1;
	}
	public void setPass1(String pass1) {
		this.pass1 = pass1;
	}
	public String getArea1() {
		return area1;
	}
	public void setArea1(String area1) {
		this.area1 = area1;
	}
	public boolean isCheck1() {
		return check1;
	}
	public void setCheck1(boolean check1) {
		this.check1 = check1;
	}
	public String[] getChecks() {
		return checks;
	}
	public void setChecks(String[] checks) {
		this.checks = checks;
	}
	public String getRadio1() {
		return radio1;
	}
	public void setRadio1(String radio1) {
		this.radio1 = radio1;
	}
	public String getRadio2() {
		return radio2;
	}
	public void setRadio2(String radio2) {
		this.radio2 = radio2;
	}
	public String getSelect1() {
		return select1;
	}
	public void setSelect1(String select1) {
		this.select1 = select1;
	}
}

JSP の、radiobuttons と submit の間に SELECT用のタグを追加する。

				<tr><td><form:radiobuttons path="radio2" name="radio2"
						items="${radiolist}" itemLabel="label" itemValue="data"
						delimiter=" " />
				</td></tr>
				<tr><td><form:select path="select1" name="select1"
					items="${optionlist}" itemLabel="label" itemValue="data"
					size="5" multiple="false" />
				</td></tr>
				<tr><td><input type="submit" ></td></tr>

GETメソッドを処理する helo() メソッドでは、FormModel の値を設定し、optionlist の名前で ListDataModel の List を渡してやる。

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		fm.setCheck1(true);
		fm.setChecks(new String[]{"Windows"});
		fm.setRadio1("male");
		fm.setRadio2("Linux");
		fm.setSelect1("Windows");
		model.addAttribute("formModel", fm);
		model.addAttribute("checkItems", getList());
		model.addAttribute("radiolist", getList());
		model.addAttribute("optionlist", getList());
		return "showMessage";
	}

POST メソッドを処理する form() メソッドでは、選択された値を表示する1行の追加と、optionlist の名前で ListDataModel の List を渡してやる1行の追加のみ。

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		String[] selected = formModel.getChecks();
		res = res + "<ol>";
		for (String sel : selected) {
			res += "<li>" + sel + "</li>";
		}
		res += "</ol>";
		res += "<br />selected: " + formModel.getRadio1();
		res += "<br />selected: " + formModel.getRadio2();
		res += "<br />selected: " + formModel.getSelect1();
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		model.addAttribute("formModel", formModel);
		model.addAttribute("checkItems", getList());
		model.addAttribute("radiolist", getList());
		model.addAttribute("optionlist", getList());
		return "showMessage";
	}

リストで複数項目を選択可能にする

<form:select> タグの multiple属性をtrueにすることで、リストの複数項目を選択可能になる。

複数選択したデータを受け取るために、FormModel に select2 を追加し、getter/setterを生成する。

FormModel.java

package jp.abc;

public class FormModel {
	private String input1;
	private String pass1;
	private String area1;
	private boolean check1;
	private String[] checks;
	private String radio1;
	private String radio2;
	private String select1;
	private String[] select2;

	public String getInput1() {
		return input1;
	}
	public void setInput1(String input1) {
		this.input1 = input1;
	}
	public String getPass1() {
		return pass1;
	}
	public void setPass1(String pass1) {
		this.pass1 = pass1;
	}
	public String getArea1() {
		return area1;
	}
	public void setArea1(String area1) {
		this.area1 = area1;
	}
	public boolean isCheck1() {
		return check1;
	}
	public void setCheck1(boolean check1) {
		this.check1 = check1;
	}
	public String[] getChecks() {
		return checks;
	}
	public void setChecks(String[] checks) {
		this.checks = checks;
	}
	public String getRadio1() {
		return radio1;
	}
	public void setRadio1(String radio1) {
		this.radio1 = radio1;
	}
	public String getRadio2() {
		return radio2;
	}
	public void setRadio2(String radio2) {
		this.radio2 = radio2;
	}
	public String getSelect1() {
		return select1;
	}
	public void setSelect1(String select1) {
		this.select1 = select1;
	}
	public String[] getSelect2() {
		return select2;
	}
	public void setSelect2(String[] select2) {
		this.select2 = select2;
	}
}

JSP の <form:select タグの multiple 属性を true にしたものを追加する。

showMessage.jsp

				<tr><td><form:select path="select1" name="select1"
					items="${optionlist}" itemLabel="label" itemValue="data"
					size="5" multiple="false" />
				</td></tr>
				<tr><td><form:select path="select2" name="select2"
					items="${optionlist}" itemLabel="label" itemValue="data"
					size="5" multiple="true" />
				</td></tr>
				<tr><td><input type="submit" ></td></tr>

コントローラで、GETメソッドを処理する helo() メソッドの変更箇所は1行のみ。

MyAppController.java

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		fm.setCheck1(true);
		fm.setChecks(new String[]{"Windows"});
		fm.setRadio1("male");
		fm.setRadio2("Linux");
		fm.setSelect1("Windows");
		fm.setSelect2(new String[]{"Linux"});
		model.addAttribute("formModel", fm);
		model.addAttribute("checkItems", getList());
		model.addAttribute("radiolist", getList());
		model.addAttribute("optionlist", getList());
		return "showMessage";
	}

POSTメソッドを処理する form() メソッドでは、選択された複数の項目を表示するコードを追加する。

MyAppController.java

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		String[] selected = formModel.getChecks();
		res = res + "<ol>";
		for (String sel : selected) {
			res += "<li>" + sel + "</li>";
		}
		res += "</ol>";
		res += "<br />selected: " + formModel.getRadio1();
		res += "<br />selected: " + formModel.getRadio2();
		res += "<br />selected: " + formModel.getSelect1();
		selected = formModel.getSelect2();
		res = res + "<ol>";
		for (String sel : selected) {
			res += "<li>" + sel + "</li>";
		}
		res += "</ol>";
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		model.addAttribute("formModel", formModel);
		model.addAttribute("checkItems", getList());
		model.addAttribute("radiolist", getList());
		model.addAttribute("optionlist", getList());
		return "showMessage";
	}

7月3日

フォームを使いこなす

練習用に新しいプロジェクトを作成してそこにフォームを作成する。
メニューで[新規]-[プロジェクト]を選択。
ウィザードで[Spring]-[Springプロジェクト]を選択。

プロジェクト名: Forms
テンプレート: Simple Spring Web Maven

「完了」をクリックしてプロジェクトを作成する。

Forms プロジェクトを右クリックし、[Maven]-[プロジェクトの更新]を選択。

プロジェクトの更新が終わったら、もう一度 Forms プロジェクトを右クリックし、[実行]-[Maven install]を選択。

Tomcat7サーバーを右クリックして「追加および除去」を選択。
Formsプロジェクトを選択して右側に移動する。
Tomcat7サーバーを再開し、 http://localhost:8080/Forms/ にアクセスする。

「click to enter」と表示されればOK。

文字化け対策をする

src/main/webapp/Web-INF の下にある web.xl を開く。

前回と同様に、web.xml の最後の </web-app> の手前に以下の内容を追加する。
web.xml

	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

FormModelを作成する

プロジェクトエクスプローラで Forms の下にある Javaリソース を展開し、src/main/java を右クリック。
[新規]-[クラス]を選択する。

新規Javaクラスのダイアログで
パッケージ名: jp.abc
名前: FormModel
を入力し「完了」をクリック。

FormModel クラスが作成されるので、インスタンス変数を追加する。
FormModel.java

package jp.abc;

public class FormModel {
	private String input1;
	private String pass1;
	private String area1;
}

メニューバーで[ソース]-[getterおよびsetterの生成]を選択する。
ダイアログで「すべて選択」をクリックし、挿入ポイントで「最後のメンバー」を選択。
「OK」をクリックすると、getter/setterが生成される。

showMessage.jspの変更

テキストp.204 リスト2-4 のとおりに変更する。
taglib ディレクティブが書かれていないので、テキストp.182を参照して追加する。
showMessage.jsp

<!DOCTYPE html>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
	<head>
		<meta charset="utf-8">
		<title>${title}</title>
	</head>
	<body>
		<h1>${title}</h1>
		<p>${message}</p>
		<table>
			<form:form modelAttribute="formModel">
				<tr><td><form:input path="input1"/></td></tr>
				<tr><td><form:password path="pass1" showPassword="on"/></td></tr>
				<tr><td><form:textarea path="area1" cols="40" rows="3"></form:textarea></td></tr>
				<tr><td><input type="submit" ></td></tr>
			</form:form>
		</table>
	</body>
</html>

mvc-config.xmlの変更

src/main/webapp/WEB-INF の下にある mvc-config.xml を開く。
context:component-scan タグの部分がコメントアウトされているのを修正し、base-package の部分を jp.abc に書き換えて保存する。

mvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="jp.abc"/>

    <mvc:annotation-driven />

	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	        <!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
	        <property name="prefix" value="/WEB-INF/view/"/>
	        <property name="suffix" value=".jsp"/>
	</bean>

</beans>

Controllerを作成する

Javaリソースの下の src/main/java 内の jp.abc パッケージを右クリックし、[新規]-[クラス]を選択する。
名前に MyAppController を入力して「完了」をクリック。
以下のコードを入力する。

MyAppController.java

package jp.abc;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MyAppController {

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		return "showMessage";
	}
}

Tomcat7サーバーを再起動し、http://localhost:8080/Forms/helo にアクセスする。
と、エラーが発生した。
エラーメッセージを確認すると、formModel がないという感じのメッセージがあるので、MyAppControllerをきちんと実装する。

MyAppController.java

package jp.abc;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MyAppController {

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		model.addAttribute("formModel", fm);
		return "showMessage";
	}
}

これで http://localhost:8080/Forms/helo にアクセスすると、エラーなく showMessage.jsp が表示されるようになった。

「クエリ送信」ボタンをクリックすると、POSTメソッドがサポートされてないというエラーが表示される。
MyAppController.java に、POSTメソッドを受け付けるためのメソッドを追加する。

MyAppController.java

package jp.abc;

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 MyAppController {

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		model.addAttribute("formModel", fm);
		return "showMessage";
	}

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li></ul>";
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		return "showMessage";
	}
}

チェックボックスの利用

チェックボックスは、<form:checkbox/> タグを使用する。

まずはチェックボックスを使えるようにするために、FormModel にチェックボックス用のフィールドを追加する。

FormModel.java

package jp.abc;

public class FormModel {
	private String input1;
	private String pass1;
	private String area1;
	private boolean check1;

	public String getInput1() {
		return input1;
	}
	public void setInput1(String input1) {
		this.input1 = input1;
	}
	public String getPass1() {
		return pass1;
	}
	public void setPass1(String pass1) {
		this.pass1 = pass1;
	}
	public String getArea1() {
		return area1;
	}
	public void setArea1(String area1) {
		this.area1 = area1;
	}
	public boolean isCheck1() {
		return check1;
	}
	public void setCheck1(boolean check1) {
		this.check1 = check1;
	}
}

アクセスしたときにチェックされた状態にするには、FormModel#setCheck1()でtrueを設定すればよい。

MyAppController.java

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		fm.setCheck1(true);
		model.addAttribute("formModel", fm);
		return "showMessage";
	}

チェックボックスの値をクエリ送信後の画面に繁栄させるには、form()メソッドで出力されるコードに&lt:li>要素を追加する。

MyAppController.java

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		return "showMessage";
	}

複数のチェックボックスをまとめて作る

複数のチェックボックスをまとめて作るには、<form:checkboxes>タグを使用する。

まずは FormModel に、複数のチェックボックスの値を格納するためのメンバーを用意する。

FormModel.java

package jp.abc;

public class FormModel {
	private String input1;
	private String pass1;
	private String area1;
	private boolean check1;
	private String[] checks;

	public String getInput1() {
		return input1;
	}
	public void setInput1(String input1) {
		this.input1 = input1;
	}
	public String getPass1() {
		return pass1;
	}
	public void setPass1(String pass1) {
		this.pass1 = pass1;
	}
	public String getArea1() {
		return area1;
	}
	public void setArea1(String area1) {
		this.area1 = area1;
	}
	public boolean isCheck1() {
		return check1;
	}
	public void setCheck1(boolean check1) {
		this.check1 = check1;
	}
	public String[] getChecks() {
		return checks;
	}
	public void setChecks(String[] checks) {
		this.checks = checks;
	}
}

次に showMessage.jsp にチェックボックス用の要素を追加する。
showMessage.jsp

<!DOCTYPE html>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
	<head>
		<meta charset="utf-8">
		<title>${title}</title>
	</head>
	<body>
		<h1>${title}</h1>
		<p>${message}</p>
		<table>
			<form:form modelAttribute="formModel">
				<tr><td><form:input path="input1"/></td></tr>
				<tr><td><form:password path="pass1" showPassword="on"/></td></tr>
				<tr><td><form:textarea path="area1" cols="40" rows="3"></form:textarea></td></tr>
				<tr><td><form:checkbox path="check1" label="checkbox 1"/></td></tr>
				<tr><td>
					<form:checkboxes items="${checkItems}" path="checks" delimiter=" "/>
				</td></tr>
				<tr><td><input type="submit" ></td></tr>
			</form:form>
		</table>
	</body>
</html>

MyAppControllerに複数のチェックボックス用のコードを追加する

getList()メソッドでチェックボックスの要素を生成する。
生成したListをmodelに設定する。

MyAppController.java

package jp.abc;

import java.util.ArrayList;
import java.util.List;

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 MyAppController {

	private List<String> getList() {
		List<String> list = new ArrayList<String>();
		list.add("Mac OS X");
		list.add("Windows");
		list.add("Linux");
		return list;
	}

	@RequestMapping(value = "/helo", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "ModelAndView sample");
		model.addAttribute("message", "これはModelAndViewのテストです。");
		FormModel fm = new FormModel();
		fm.setCheck1(true);
		fm.setChecks(new String[]{"Windows"});
		model.addAttribute("formModel", fm);
		model.addAttribute("checkItems", getList());
		return "showMessage";
	}

	@RequestMapping(value = "/helo", method = RequestMethod.POST)
	public String form(@ModelAttribute FormModel formModel, Model model){
		String res = "<ul><li>" + formModel.getInput1()
				+ "</li><li>" + formModel.getPass1()
				+ "</li><li>" + formModel.getArea1()
				+ "</li><li>" + formModel.isCheck1()
				+ "</li></ul>";
		model.addAttribute("title", "sample");
		model.addAttribute("message", res);
		return "showMessage";
	}
}