単純なBeanフィールド検証
Beanフィールドのチェックについては、以前Apache BValで検討したことがありますが、今はこの商品も使いたくないので、依存が少ないのは一つです.自分でやって、JSR 303の仕様通りに完全に実現するのは面倒で、その必要はありません.そこで取捨選択して、やはりJSR 303の注釈を制約条件として、この仁兄の反射に基づくやり方を参考にして、自分でBean検査を実現します.
原理は総じて言えば、反射+カスタム関数インタフェース(Java 8)+Map関連注釈と検証の実現は、比較的簡単で、せいぜい100行のコードで完成して、すべて私たちが十分に使えばいいという要求に基づいて、その他のBBはそんなに多くなくて、もし本当に問題があれば、その時になってからにします.
まず単測を書きます.Beanは以下の通りです.
JSRの
カスタム関数インタフェース
原理は総じて言えば、反射+カスタム関数インタフェース(Java 8)+Map関連注釈と検証の実現は、比較的簡単で、せいぜい100行のコードで完成して、すべて私たちが十分に使えばいいという要求に基づいて、その他のBBはそんなに多くなくて、もし本当に問題があれば、その時になってからにします.
まず単測を書きます.Beanは以下の通りです.
class News {
@NotNull
private long id;
@NotBlank(message = " ")
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
JSRの
@NotNull
と@NotBlank
はそれぞれidとname属性にバインドされ、制約idフィールドはnullではなく、idはlongタイプであるため、0でもないことがわかる.nameプロパティは空の文字列ではありません.nameプロパティは、エラー時のメッセージもカスタマイズします.カスタム関数インタフェース
JDKが持つ関数インタフェースタイプが満たされない場合は、関数インタフェースをカスタマイズします.BiFunction
は2つのパラメータしかサポートできません.現在、私たちのシーンはBean属性の値です.1つはBean属性オブジェクト自体(Field、フィールドオブジェクトとも呼ばれ、反射されています)です.最後に制約条件、すなわち注釈です.合計3つのパラメータなので、BiFunction
は満足できません.以下に示すように、自分で書くしかありません.package com.ajaxjs.validator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
@FunctionalInterface
public interface Validator {
/**
*
*
* @param value Bean
* @param field Bean
* @param ann Bean
* @return , null
*/
public String valid(Object value, Field field, Annotation ann);
}
戻り値はStringであり、エラー情報を指し、通過するとnullを返し、nullでないとどの属性(フィールド)が要求に合致しないかを説明し、このStringが要求に合致しない理由である.
ベリファイアストレージ構造
どのようにもっとよく表現するか分からないが、記憶構造--変なようで、どうせ、簡単なMap:keyは注釈クラスで、valueは検証コードで、このようにそれらは1対1の関係を構成して、静的なメンバーとして保存しています.どう使いますか.下で反射すると、あなたが見るとMapのように使われていることがわかり、少しも複雑ではありません.package com.ajaxjs.validator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import com.ajaxjs.util.logger.LogHelper;
public class BeanValidator {
private static final LogHelper LOGGER = LogHelper.getLog(BeanValidator.class);
/**
*
*/
private static final Map<Class<?>, Validator> cache = new HashMap<>();
/**
*
*
* @param clzs
* @param validator lambda
*/
public static void register(Class<?> clzs, Validator validator) {
cache.put(clzs, validator);
}
static {
register(NotNull.class, BuiltinValidator.NOT_NULL_VALIDATOR);
register(NotBlank.class, BuiltinValidator.NOT_BLANK_VALIDATOR);
}
……
}
ベリファイアが使用する前に登録する必要があるのは、putがMapに入ったことにほかならない.例えばregister(NotNull.class, BuiltinValidator.NOT_NULL_VALIDATOR);
だ.NOT_NULL_VALLIDATORは、関数インタフェースを適用するベリファイアであり、@NotNull
の場合に対応する.NOT_NULL_VALLIDATORは普通のlambdaで、前に言ったように、関数のパラメータと戻り値を把握することです.具体的な用途は何ですか.なぜそれらのパラメータを伝えますか.足りますか.どのタイプの結果を返しますか?NOT_NULL_VALLIDATORのソースコードは以下の通りです.public static final Validator NOT_NULL_VALIDATOR = (value, field, ann) -> {
if (value == null) {
NotBlank n = (NotBlank) ann;
return n.message() != null ? n.message() : field.getName() + " null";
} else if (value != null && value instanceof Number) {
Number num = (Number) value;
if (num.equals(0) || num.equals(0L)) {
NotNull n = (NotNull) ann;
return n.message() != null ? n.message() : field.getName() + " null";
} else
return null;
} else
return null;
};
検証の実行
使い方を学ぶだけなら、上の原理的な内容は見なくてもいいです.ただ、呼び出し者APIの唯一の暴露方法BeanValidator.validate(Object bean)
を学ぶだけです.ここでは、Beanの反射動作について、Beanの要件に合致するか否かを判断するために必要な情報を取得する./**
*
*
* @param bean
* @return , length=0
*/
public static String[] validate(Object bean) {
List<String> list = new ArrayList<>();
Class<?> cls = bean.getClass();
Field[] fields = cls.getDeclaredFields();
try {
//
for (Field f : fields) {//
f.setAccessible(true);
Object value = f.get(bean);//
Annotation[] arrayAno = f.getAnnotations();//
for (Annotation annotation : arrayAno) {
Class<?> clazz = annotation.annotationType();// ( Class)
Validator validator = cache.get(clazz);
if (validator == null) //
continue;
String result = validator.valid(value, f, annotation);
if (result != null)
list.add(result);
}
}
} catch (Exception e) {
LOGGER.warning(e, " ");
}
return list.toArray(new String[list.size()]);
}
小結
BuiltinValidatorに組み込まれた検証コードは、非空、Max/Min/Sizeなどの一般的な状況、つまりJSRデフォルトを考慮しています.ユーザーは引き続き拡張して、自分の検証コードを与えて、それから登録すればいいです.身分証明書の検証を書いてみるより......読者に残しておきましょう.
以上のすべてのソースコードはhttps://gitee.com/sp42_admin/ajaxjs見つけます.
package com.ajaxjs.validator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
@FunctionalInterface
public interface Validator {
/**
*
*
* @param value Bean
* @param field Bean
* @param ann Bean
* @return , null
*/
public String valid(Object value, Field field, Annotation ann);
}
どのようにもっとよく表現するか分からないが、記憶構造--変なようで、どうせ、簡単なMap:keyは注釈クラスで、valueは検証コードで、このようにそれらは1対1の関係を構成して、静的なメンバーとして保存しています.どう使いますか.下で反射すると、あなたが見るとMapのように使われていることがわかり、少しも複雑ではありません.
package com.ajaxjs.validator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import com.ajaxjs.util.logger.LogHelper;
public class BeanValidator {
private static final LogHelper LOGGER = LogHelper.getLog(BeanValidator.class);
/**
*
*/
private static final Map<Class<?>, Validator> cache = new HashMap<>();
/**
*
*
* @param clzs
* @param validator lambda
*/
public static void register(Class<?> clzs, Validator validator) {
cache.put(clzs, validator);
}
static {
register(NotNull.class, BuiltinValidator.NOT_NULL_VALIDATOR);
register(NotBlank.class, BuiltinValidator.NOT_BLANK_VALIDATOR);
}
……
}
ベリファイアが使用する前に登録する必要があるのは、putがMapに入ったことにほかならない.例えば
register(NotNull.class, BuiltinValidator.NOT_NULL_VALIDATOR);
だ.NOT_NULL_VALLIDATORは、関数インタフェースを適用するベリファイアであり、@NotNull
の場合に対応する.NOT_NULL_VALLIDATORは普通のlambdaで、前に言ったように、関数のパラメータと戻り値を把握することです.具体的な用途は何ですか.なぜそれらのパラメータを伝えますか.足りますか.どのタイプの結果を返しますか?NOT_NULL_VALLIDATORのソースコードは以下の通りです.public static final Validator NOT_NULL_VALIDATOR = (value, field, ann) -> {
if (value == null) {
NotBlank n = (NotBlank) ann;
return n.message() != null ? n.message() : field.getName() + " null";
} else if (value != null && value instanceof Number) {
Number num = (Number) value;
if (num.equals(0) || num.equals(0L)) {
NotNull n = (NotNull) ann;
return n.message() != null ? n.message() : field.getName() + " null";
} else
return null;
} else
return null;
};
検証の実行
使い方を学ぶだけなら、上の原理的な内容は見なくてもいいです.ただ、呼び出し者APIの唯一の暴露方法BeanValidator.validate(Object bean)
を学ぶだけです.ここでは、Beanの反射動作について、Beanの要件に合致するか否かを判断するために必要な情報を取得する./**
*
*
* @param bean
* @return , length=0
*/
public static String[] validate(Object bean) {
List<String> list = new ArrayList<>();
Class<?> cls = bean.getClass();
Field[] fields = cls.getDeclaredFields();
try {
//
for (Field f : fields) {//
f.setAccessible(true);
Object value = f.get(bean);//
Annotation[] arrayAno = f.getAnnotations();//
for (Annotation annotation : arrayAno) {
Class<?> clazz = annotation.annotationType();// ( Class)
Validator validator = cache.get(clazz);
if (validator == null) //
continue;
String result = validator.valid(value, f, annotation);
if (result != null)
list.add(result);
}
}
} catch (Exception e) {
LOGGER.warning(e, " ");
}
return list.toArray(new String[list.size()]);
}
小結
BuiltinValidatorに組み込まれた検証コードは、非空、Max/Min/Sizeなどの一般的な状況、つまりJSRデフォルトを考慮しています.ユーザーは引き続き拡張して、自分の検証コードを与えて、それから登録すればいいです.身分証明書の検証を書いてみるより......読者に残しておきましょう.
以上のすべてのソースコードはhttps://gitee.com/sp42_admin/ajaxjs見つけます.
/**
*
*
* @param bean
* @return , length=0
*/
public static String[] validate(Object bean) {
List<String> list = new ArrayList<>();
Class<?> cls = bean.getClass();
Field[] fields = cls.getDeclaredFields();
try {
//
for (Field f : fields) {//
f.setAccessible(true);
Object value = f.get(bean);//
Annotation[] arrayAno = f.getAnnotations();//
for (Annotation annotation : arrayAno) {
Class<?> clazz = annotation.annotationType();// ( Class)
Validator validator = cache.get(clazz);
if (validator == null) //
continue;
String result = validator.valid(value, f, annotation);
if (result != null)
list.add(result);
}
}
} catch (Exception e) {
LOGGER.warning(e, " ");
}
return list.toArray(new String[list.size()]);
}
BuiltinValidatorに組み込まれた検証コードは、非空、Max/Min/Sizeなどの一般的な状況、つまりJSRデフォルトを考慮しています.ユーザーは引き続き拡張して、自分の検証コードを与えて、それから登録すればいいです.身分証明書の検証を書いてみるより......読者に残しておきましょう.
以上のすべてのソースコードはhttps://gitee.com/sp42_admin/ajaxjs見つけます.