menu
書いてる野郎
orebike@gmail.com
自分で作るオリジナルのバリデーションを作ると。
今回は例としてリストの全部の値がLong型に変換できるか確認する @LongList
というものを作ってみる。
まずアノテーション自体を作る。
import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.ElementType; import org.seasar.struts.annotation.Arg; import org.seasar.struts.annotation.Msg; import org.seasar.struts.annotation.Validator; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @Validator("longList") public @interface LongList { Msg msg() default @Msg(key = "errors.long"); Arg arg0() default @Arg(key = ""); String target() default ""; }
内容はほぼ定型句である。Long型のListを受け取るようなパラメータはほぼチェックボックスなので、 エラー処理もエラーと判断できればいいぐらいで特に何も考える必要は無い
@Validator(“longList”)
の部分だけは覚えておこう
次にチェック処理そのものを書く。
import java.lang.reflect.InvocationTargetException; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.validator.Field; import org.apache.commons.validator.GenericValidator; import org.apache.commons.validator.ValidatorAction; import org.apache.struts.action.ActionMessages; import org.apache.commons.validator.Validator; import org.seasar.struts.validator.S2FieldChecks; public class OreS2FieldChecks extends S2FieldChecks { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") public static boolean validateLongList( Object bean, ValidatorAction validatorAction, Field field, ActionMessages errors, Validator validator, HttpServletRequest request) { List<String> valueList = null; try{ valueList = (List<String>) PropertyUtils.getProperty(bean, field.getProperty()); }catch(IllegalAccessException e){ addError(errors, field, validator, validatorAction, request); return false; }catch(InvocationTargetException e) { addError(errors, field, validator, validatorAction, request); return false; }catch(NoSuchMethodException e){ addError(errors, field, validator, validatorAction, request); return false; } if(valueList == null){ return true; } if(valueList.isEmpty()){ return true; } for(String v : valueList){ if(!GenericValidator.isLong(v)){ addError(errors, field, validator, validatorAction, request); return false; } } return true; } }
S2FieldChecks
を継承しているのは他のチェックがここに実装されているからだ。
それに合わせているだけ、実装内容を同じにするならば特に継承しなくてもいい。
メソッドのシグネチャは他のValidator の実装がそうなっているからそれに合わせているだけ
次に値を取得する。なんのチェックも無しにいきなりキャストして取り込んでいるが、
そもそもこれは List<String>
の型にツケられるという前提があるので細かいチェックをしていない
valueList = (List<String>) PropertyUtils.getProperty(bean, field.getProperty());
List じゃない Stringの取得方法の実装は親クラスにあるので必要ならばそっちを参考に。
あとはグルグル回してそれが Long 型に変換できるのかをチェックするだけ。
戻りとしてOKNGを戻しているのだが、実際のエラー捕捉は addError されているか否かで決定される。 false を戻したからエラーと認識されるのではない。なので false を返す直前で addError している。
これはほぼ定型句
異なるライブラリに似た名前のクラスが沢山あるのでimport を注意深くしないと間違える
次にSAStruts 側で使えるようにする
validator-rules.xml に既存のチェック用記述が沢山あるのでその中から一個コピーして今回の設定に合わせる name を アノテーションの時に設定した名前に一致させる。 class をフルパッケージ名で指定、使うメソッド名も指定、パラメータは同じなのでそのままスライド
<validator name="longList" classname="hoge.piyo.fuga.OreS2FieldChecks" method="validateLongList" methodParams="java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field, org.apache.struts.action.ActionMessages, org.apache.commons.validator.Validator, javax.servlet.http.HttpServletRequest" depends="" msg="errors.long"/>
これで後は List<String>型のForm のプロパティにアノテーションのをくっつければ
@LongList List<String> hoge;
アクセス時にチェックが走る。
今回はエラーメッセージは errors.long の LongType のチェックと共用しているので、作ってない。