m-namikiの日記

おもしろき こともなき世を おもしろく

SpringMVC3.2.1を利用してのWebアプリケーション #03

前回の続きです。前回はHelloWorldを表示させましたので、今回はフォームを使って画面の入力情報の受け取りを行います。

入力用JSPの作成

まずは入力画面の作成を行います。メールアドレスとパスワードの入力欄及びサブミットボタンからなる単純な画面です。ついでにQuickstartに付属してたTwitter Bootstrapも使ってみます。

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

<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css" />" rel="stylesheet" media="screen" />
<link href="<c:url value="/resources/css/core.css" />" rel="stylesheet" media="screen" />
<title>Input - Input</title>
</head>
<body>
<div class="container">
	<form:form modelAttribute="inputCommand" action="input.html" method="POST">
		メールアドレスとパスワードを入力してください。<br>
		<form:input path="mailAddress" class="input-large" placeholder="メールアドレス"/>
		<form:errors path="mailAddress" class="text-error"/><br>
		<form:password path="password" class="input-large" placeholder="パスワード"/>
		<form:errors path="password" class="text-error"/><br>
		<input type="submit" value="送信" class="btn btn-primary"/>
	</form:form>
</div>
</body>
</html>

Commandクラスの実装

入力情報を保持するためのCommandクラスを実装します。入力項目に対するプロパティとgetter/setterを定義します。

package jp.co.shantery.tutorial.web.input.command;

import java.io.Serializable;

import org.apache.commons.lang3.builder.ToStringBuilder;

/**
 * input.jspで入力された情報を受け取るコマンドクラスです。
 * 
 * @author m-namiki
 * 
 */
public class InputCommand implements Serializable {

	private static final long serialVersionUID = 1L;

	/** メールアドレスです。 */
	private String mailAddress;

	/** パスワードです。 */
	private String password;

	public String getMailAddress() {
		return mailAddress;
	}

	public void setMailAddress(String mailAddress) {
		this.mailAddress = mailAddress;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}
}

デバック用にtoString()も実装しておきます。HttpSessionに格納する可能性もあるので、Serializable を実装しています。
また上記ではプロパティはString型のみですが、Integer型なども使用することができます。ただし、プリミティブ型(int, long, double, char... etc)は使用しない方が良いらしいです。理由としては、プリミティブ型の場合、HTMLで値が空白(=null)を表現できないためです。

Controllerクラスの実装

画面の遷移先を制御するコントローラクラスを実装します。また今回は入力チェックなどもコントローラクラスで実装します。*1

/**
 * 入力情報の受け取りを行うコントローラクラスです。
 * 
 * @author m-namiki
 * 
 */
@Controller
@RequestMapping(value = "/input")
public class InputController {

	/** コマンド名です。 */
	public static final String INPUT_COMMAND_NAME = "inputCommand";

	/** 入力画面のパスです。 */
	private static final String PAGE_INPUT = "input/input";

	/** 結果画面のパスです。 */
	private static final String PAGE_RESULT = "input/result";

	/** ロガーです。 */
	private static Logger logger = Logger.getLogger(InputController.class);

	/**
	 * コマンドの初期オブジェクトを作成します。<br>
	 * このメソッドを定義しなくてもコントローラとして動作しますが、バインドエラー時などに呼び出されるため存在しないとシステムエラーとなることがあります。
	 * 
	 * @return コマンド
	 */
	@ModelAttribute(INPUT_COMMAND_NAME)
	public InputCommand createInputCommand() {
		InputCommand command = new InputCommand();
		return command;
	}

	/**
	 * 初期表示の準備処理です。
	 * 
	 * @param model
	 *            画面モデル
	 */
	@RequestMapping(method = RequestMethod.GET)
	public String init(Model model) {
		logger.info("init() Strat.");
		InputCommand command = createInputCommand();
		model.addAttribute(INPUT_COMMAND_NAME, command);
		logger.info("init() End.");

		return PAGE_INPUT;
	}

	/**
	 * 画面で入力された情報を受け取り、結果画面を表示します。
	 * 
	 * @param command
	 *            入力情報
	 * @param result
	 *            入力チェック結果
	 * @return hello_result.jspのパス
	 */
	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView next(
			@ModelAttribute(INPUT_COMMAND_NAME) InputCommand command,
			BindingResult result) {
		logger.info("next() Strat.");

		// 入力チェック
		if (StringUtils.isEmpty(command.getMailAddress())) {
			result.rejectValue("mailAddress", "errors.required");
		}
		if (StringUtils.isEmpty(command.getPassword())) {
			result.rejectValue("password", "errors.required");
		}

		ModelAndView view = new ModelAndView();

		// チェックエラーの場合は自画面遷移
		if (result.hasErrors()) {
			view.getModel().putAll(result.getModel());
			view.setViewName(PAGE_INPUT);
			return view;
		}

		view.setViewName(PAGE_RESULT);
		view.addObject("name", command.getMailAddress());
		logger.info("next() End.");
		return view;
	}
}
messages_ja_JP.properties

上記のコントローラクラスで入力チェックに抵触した場合、BindingResult#rejectValue()でプロパティ名とエラーコードを設定していますが、このエラーコードは messages.properties からエラーメッセージを取得する際のキーとなるので、messages.properties を作成しておきます。パスはspringmvc-tutorial/src/main/resources/messages_ja_JP.propertiesです。*2

errors.required=必須項目です。

native2asciiは適宜行ってください。Eclipseの場合、プロパティエディタ を使えばnative2asciiをイチイチ行う必要がないので便利です。

表示用JSPの作成

最後に表示用JSPを作成します。入力画面で入力されたメールアドレスを表示します。

<%@ page language="java" trimDirectiveWhitespaces="true"
	contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css" />" rel="stylesheet" media="screen" />
<link href="<c:url value="/resources/css/core.css" />" rel="stylesheet" media="screen" />
<title>Input - Result</title>
</head>
<body>
<div class="container">
	<c:out value="${name}" /> さん、こんにちは。
</div>
</body>
</html>

確認

tomcat-maven-plugin から Tomcat7 を起動して、http://localhost:8080/springmvc-tutorial/input.html にアクセスすると InputController#init() が呼ばれ、input.jsp を表示します。input.jspで何も入力せずに送信ボタンをクリックすると以下のような画面が表示されます。

メールアドレスとパスワードを入力して送信ボタンをクリックすると以下のような画面になります。

今回はここまで。次回以降は何をやろうかちょっと思案中です。

*1:単純な入力チェックはValidatorクラスなどで行うことも可能です

*2:メッセージの国際化のためにロケール名を追加しましたがなくて良いかも