SpringMVCでFormをバリデーションしてバリューオブジェクトにセットしてコントローラで扱う

SpringMVCでFormのバリデーションどうやるか?っていうのを調べてたら、
どうやらJSR 303: Bean Validationってのでやりくりするみたいです。
Spring3のドキュメントみてもそんな風に書いてあります→ 5.7 Spring 3 Validation
 
ということで、さっそく実装してみます。
 
入力はHTMLから普通にFormをSubmitするわけなんですが、Springのタグラリブラリ使って、
modelAttribute=”hoge”って感じでサーバ側に送ってあげます。
■ 入力画面のJSP

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ page session="false" %>
<html>
<body>
<form:form modelAttribute="hoge" method="POST" action="/aaa/hoge/regist">
  <input type="text" name="hogeId" value="999" />
  <input type="text" name="hogeStr" value="hogehogehoge" />
  <input type="submit" value="Save" />
</form:form>
</body>
</html>

 
■ 受け取るコントローラ
以下のようにコレといってなんにもしないでバリューオブジェクトにセットしてくれて
Controllerから扱えます。楽チンです。

@RequestMapping(value = "/hoge/regist", method = RequestMethod.POST)
public String regist(Hoge hoge, Locale locale, Model model) {

    logger.info(String.valueOf(hoge.getHogeId()));
    logger.info(hoge.getHogeStr());

 
■ Validation
お仕事でシステム作ってると、必ず必要になってくるのがバリデーションです。
↓とかみるとHibernateのValidatorを使おうって感じみたいです。
http://d.hatena.ne.jp/yamkazu/20110206/1296985545
http://blog.jteam.nl/2009/08/04/bean-validation-integrating-jsr-303-with-spring/
 
ってことで、以下のようにJBossのリポジトリ足してhibernate-validatorのjarの定義入れます。
#JBossもHibernateも使わないのになんかちょっとシャクですが。。

~略~
<repository>
    <id>JBoss Repo</id>
    <name>JBoss Repo</name>
    <url>https://repository.jboss.org/nexus/content/repositories/releases</url>
</repository>
~略~
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.2.0.Final</version>
</dependency>

 
バリデーションに関しては、コントローラーで受け取る引数に、
以下のように@Validアノテーションを入れる感じになります。お手軽。。

public String regist(@Valid Hoge hoge, Locale locale, Model model) {

 
で、バリューオブジェクトに以下のようなアノテーションを付けてみます。
IDは99がMAXで、文字列はNotNullですよ、と。

public class Hoge {
    @Max(99)
    private int hogeId;
    @NotNull
    private String hogeStr;

 
IDに99、と文字列にhogehogehogeを入力してサブミットすると、
以下のように普通に値が取れますが、

INFO : com.shinodogg.HogeController - HOGE Regist Start
INFO : com.shinodogg.HogeController - 99
INFO : com.shinodogg.HogeController - hogehogehoge

IDを100にすると、、以下のようにバリデーションエラーになります。

例外

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'hoge' on field 'hogeId': rejected value [100]; codes [Max.hoge.hogeId,Max.hogeId,Max.int,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [hoge.hogeId,hogeId]; arguments []; default message [hogeId],99]; default message [must be less than or equal to 99]
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:656)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
原因

org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'hoge' on field 'hogeId': rejected value [100]; codes [Max.hoge.hogeId,Max.hogeId,Max.int,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [hoge.hogeId,hogeId]; arguments []; default message [hogeId],99]; default message [must be less than or equal to 99]
	org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:810)

 
後は、500エラーを返すのではなく、ちゃんとキャッチしてメッセージをそれっぽいのにして、
クライアントに返してやる必要がありますが、そこから先は @atushi がイイ感じにやりくりしてくれるでしょうw
 
ちなみに@atushiは、iFieldRecという↓なiPhoneアプリを最近リリースしましたw
[youtube https://www.youtube.com/watch?v=Vqpo1ONC_Lg&w=560&h=315]
85円で買えますので是非どうぞw↓
http://itunes.apple.com/en/app/ifieldrec/id456579902?mt=8
 

よくわかるiPhoneアプリ開発の教科書【Xcode 4対応版】
森 巧尚
毎日コミュニケーションズ
売り上げランキング: 600

コメント

  1. atushi より:

    宣伝ありがとうございますmm
    SFに行っている間、日本でなんとかNG○○を形にします!

タイトルとURLをコピーしました