かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Spring Bootで入力値の検証(バリデーション)の順番を制御する

okazuki.hatenablog.com

基本的に上の記事の通りでいいんですが、複数の属性を同じプロパティにつけた場合に、一気にバリデーションが実行されてエラーメッセージがうざいことになってしまいます。例えば以下のようなBeanがあったとして。

package okazuki.validationEdu;

import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;

public class Person {
    @NotEmpty(message = "なまえ入れてね")
    @Length(min = 1, max = 10, message = "1~10の間")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    
}

フォームに何も入力せずにPOSTすると以下のようにNotEmptyとLength両方がバリデーションされてしまいます。

f:id:okazuki:20150713205957p:plain

NotEmptyでエラーになったときはLengthはエラーチェックしなくてもいいという状況に対応するにはgroupsを使います。

以下のようにバリデーションをグルーピングするためのインターフェースを用意します。

package okazuki.validationEdu;

public interface First {

}
package okazuki.validationEdu;

public interface Second {

}

そして、これを束ねるためのインターフェースも用意します。

package okazuki.validationEdu;

import javax.validation.GroupSequence;

@GroupSequence({First.class, Second.class})
public interface All {

}

そして、Personクラスの属性にFirstとSecondを設定します。

package okazuki.validationEdu;

import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;

public class Person {
    @NotEmpty(message = "なまえ入れてね", groups = First.class)
    @Length(min = 1, max = 10, message = "1~10の間", groups = Second.class)
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    
}

最後にControllerで@Validated属性に、Allを指定します。

package okazuki.validationEdu;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HomeController {

    @RequestMapping
    public String index(@ModelAttribute("form") Person p) {
        return "index";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String indexPost(@ModelAttribute("form") @Validated(All.class) Person p, BindingResult r) {
        return "index";
    }
}

こうすると、Firstのgroupのバリデーションを実行してエラーになったらそこでとまります。ここでいうとNotEmptyだけが実行されるようになります。NotEmptyを通過したらLengthがチェックされます。