アノテーションでバリデーション
Beanでバリデーションするなら、Beanに定義を持たせて、実際のバリデーション処理は違うクラスでやるべきだよね、と言う話になったのでそんな感じのものを作ってみました。
@Retention(RetentionPolicy.RUNTIME) public @interface Validation { //最小文字数を定義 int min() default 1; // 最大文字数を定義 int max(); // その項目の正規表現を定義 String regex() default ""; }
public class SampleBean { @Validation( min=1, max=10 ) private String name; @Validation( max=3, regex="\\d+" ) private String old; @Validation( max=11, regex="\\d{2,4}-\\d{2,4}-\\d{4}" ) private String phone; (中略) }
フィールドにアノテーションで定義情報を持たせています。この定義情報でもってバリデーションします。
public class SampleBeanValidator { public static String validate( String elem, String fieldName ) { Validation val = getValidation( SampleBean.class, fieldName ); if( val.min() > elem.length() || val.max() < elem.length() ) return "文字数的にアレですよ"; if( !elem.matches( val.regex() ) ) return "規則的に正しくないですよ"; return null; } public static Validation getValidation( Class clazz, String fieldName ) { Validation validation = null; try{ validation = clazz.getDeclaredField( fieldName ).getAnnotation(Validation.class); }catch( NoSuchFieldException nsfe ){ nsfe.printStackTrace(); } return validation; } }
なんでvalidateメソッドがStringを返すんですか、というのは便宜上なのであまり気にしないでもらいたいのです。
public class ValidatorTest { public static void main(String[] args) { SampleBean bean = new SampleBean(); bean.setName("にゃんぽこにゃん3世の登場です"); bean.setOld("1d"); bean.setPhone("90-32-4343"); System.out.println( SampleBeanValidator.validate( bean.getName(), "name" ) ); System.out.println( SampleBeanValidator.validate( bean.getOld(), "old" ) ); System.out.println( SampleBeanValidator.validate( bean.getPhone(), "phone" ) ); } }
すると
文字数的にアレですよ 規則的に正しくないですよ null
と返ってきます。ValidationにNOT NULLだの何だの加えていくと楽しいのではないかと。
それにつけても@Retention(RetentionPolicy.RUNTIME)を指定しないとアノテーションをリフレクションで読めないというのは罠だと思ったよ! 凄い勢いでハマったよ!