javaでのバリデーション 〜bean validation篇〜

Post on 21-Jul-2015

1.156 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Javaでのバリデーション〜Bean Validation篇〜

2014/12/04 Validation Night at Line@eiryu

なにをやっているのか

● Twitter @eiryu○ http://eiryu.com

● 仕事○ インフラ・情シス

● バッググラウンド○ Webアプリケーションエンジニア

■ Java● Spring Framework

■ Groovy■ JavaScript■ PostgreSQL

なにをやっているのか

なぜやるのか

● 人間なのでヒューマンエラーは付きもの● バリデーションされてなかったことによる壊れた

ユーザーデータはマーケティングにも生かせない○ 男性で妊娠している等

● Webアプリケーションの場合、最悪ユーザー情報が漏洩したり、操作されたりする

どうやってやっているのか

● Bean Validationを利用● Webアプリケーションのコントローラでユーザー

入力をチェック● 単体テスト(JUnit)で想定しうる不正な入力のテ

スト

※フレームワークはSpring Bootを利用

こんなことやります

Bean Validationで(ry

以上、Wantedly四段活用でした!

Bean Validationとは

“JavaBeansのバリデーション(値の検証)のため

のメタデータモデルとAPIを定めたJavaのソフトウェアフレームワーク”

Wikipedia

http://beanvalidation.org/

Bean Validationの沿革

2009 Bean Validation 1.0(JSR 303)2013 Bean Validation 1.1(JSR 349)

JSRとは

Java Specification Requestsの略。日本語だと、Java仕様要望。個人的にはJava版のRFCと捉えている。

何がうれしいのか

● あらかじめよく使う制約(チェック)が用意されている○ Constraintsと呼ぶ

● ユーザーの入力を受け取るJavaBeans(POJO)にアノテーションで記載するため、POJOに対してテストが書ける○ コントローラのメソッド内でチェックしているとリクエストを

エミュレートするテストを書かなければならない

Constraintsの例

● @NotNull○ nullでないこと

● @Pattern○ 指定した正規表現にマッチすること

● @Size○ 文字列等のサイズが指定した範囲であること

● @AssertTrue○ trueであること

● @Future○ JVMの現在日時より未来であること

packageはjavax.validation.constraints

ここで一般的なバリデーションの話に戻ると。。

バリデーションの種類

● 単項目チェック● 相関チェック

単項目チェック

● 1つの項目に対するチェック● 例

○ ユーザー登録で名前の入力は必須だが、入力されてい

るか?

相関チェック

● 2つ以上の項目にまたがるチェック● 例

○ 性別で男性を選択しているのに、妊婦の項目にチェック

していないか?

コード例

コード例

以下のようなフィールドを持つUserFormがあるとする

● 名前(name)● 性別(sex)● 妊娠しているか(pregnant)

コード例 単項目チェック

@NotNull(message = "性別がぬるぽ")private Sex sex;

コード例 単項目チェック

● フィールドまたはそのgetterにConstraintsを付与

コード例 相関チェック

@AssertTrue(message = "男性なのに妊娠してるって言ってる。。")public boolean isValidPregnant() {

// 性別が入力されていない時は、そちらで引っかかるのでバリデーショ

ンしない

if (sex == null) {return true;

}// 妊娠していると選択している人が女性であることをチェック

if (pregnant) {return Sex.FEMALE == sex;

} return true;

}

コード例 相関チェック

● メソッドを定義してそこにアノテーションを付与● 個人的には@AssertTrueのみ利用すれば良い

と思う○ Bean ValidationのValidatorのお作法的に、isValidでバ

リデーションOKならばtrueを返すようになっている。その

流れに沿った方が分かりやすい

コード例 単体テスト(特定プロパティのみのバリデーション)

private Validator validator =Validation.buildDefaultValidatorFactory().getValidator();

@Testpublic void validateName_正常系() {

UserForm userForm = new UserForm();

userForm.setName("eiryu");Set<ConstraintViolation<UserForm>> violations =

validator.validateProperty(userForm, "name");LOGGER.info("violations: " + violations);

assertThat(violations, hasSize(0));}

コード例 単体テスト(JavaBeans全体のバリデーション)

private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

@Testpublic void validate_正常系() {

UserForm userForm = new UserForm();userForm.setName("eiryu");userForm.setSex(Sex.MALE);userForm.setPregnant(false);

Set<ConstraintViolation<UserForm>> violations =validator.validate(userForm);

LOGGER.info("violations: " + violations);

assertThat(violations, hasSize(0));}

コード例 Webアプリケーション(Spring Bootのコントローラ)

@RequestMapping("registor")public String registor(

@Valid UserForm userForm, BindingResult bindingResult) {

if (bindingResult.hasErrors()) {LOGGER.warn("bindingResult: " + bindingResult);return "index";

}// some process..

return "redirect:/complete";}

気にすべきポイント・TIPS

気にすべきポイント・TIPS(バリデーションの順番)

● 普通に使うと、バリデーションが行われる順番はランダム

○ Webアプリケーションでメッセージを上部に列挙するよう

な場合に注意

○ 相関チェックでは、関係するフィールドが単項目チェック

済みでないことに注意して実装する必要がある

気にすべきポイント・TIPS(バリデーションの順番)

● Group、 Group sequence という仕組みを使うとバリデーションの順番を制御することが出来る

○ JSRのSpecの例では、バリデーションで非常に重い処

理があって、それは他のバリデーションがOKだった時の

み実行する、というもの

○ 他に想定出来るのは、同時に2つ以上エラーになってい

るのに1つずつエラーメッセージ出すとか?

気にすべきポイント・TIPS(メッセージ)

メッセージはプロパティファイルに外だし可能。ロケールごとのファイルを用意すればi18n対応も可能

● ValidationMessages.properties● ValidationMessages_ja_JP.properties

プロパティファイルのエンコーディングはISO-8859-1で作成すること(昭和か!)

● IDEの自動変換かnative2ascii(昭和か!)で頑張りましょう

@NotNull(message = "{NotNull.sex}")private Sex sex;

気にすべきポイント・TIPS(その他)

● JavaBeansの中にJavaBeansがあるようなケースでは、そのフィールドに対して@Validアノテーションを付与すれば再帰的にバリデーションされる

public class UserForm {...

@Validprivate Address address;

...}

ご清聴ありがとうございました

top related