Spring Boot汎用インターフェースパラメータ検証を実現

10442 ワード

原文リンク:www.cphermagic.cn/spring-boot…
本明細書では、Spring BootおよびJDK8に基づいてAOPを作成し、カスタム注釈と併せて共通のインターフェースパラメータ検証を実施する.
由緒
現在のパラメータ検証でよく使用される方法は、エンティティクラスに注釈を追加することであるが、異なる方法については、適用される検査規則も異なる.例えば、AccountVOエンティティがある.
public class AccountVO {
    private String name; //   
    private Integer age; //   
}
ユーザー登録には名前と年齢を記入する必要があります.ユーザー登録には名前だけを記入すればいいです.検証規則を実体類に加えると明らかに不適切です.
したがって、同じエンティティパラメータに対して、異なる方法が異なる検査規則を適用することができ、このツールが誕生し、日常の作業で長く使用されています.
紹介する
まず使用方法を見てみます.
@Service
public class TestImpl implements ITestService {

    @Override
    @Check({"name", "age"})
    public void testValid(AccountVO vo) {
        // ...
    }

}
この方法の@Checkは、パラメータAccountVOnameageの属性が空ではないことを注釈している.空チェック以外にも、サイズ判定、イコールチェックをサポートします.
@Check({"id>=8", "name!=aaa", "title<10"})
デフォルトのエラー情報はフィールドに戻ります.エラーの原因と呼び出しの方法、例えば:
updateUserId must not null while calling testValid

id must >= 8 while calling testValid

name must != aaa while calling testValid
カスタムエラーリターン情報もサポートされています.
@Check({"title<=8:       8  ,     "})
public void testValid(TestPO po) {
    // ...
}
チェックルールの後に:を追加するだけで、後にカスタム情報を記入すると、デフォルトのエラー情報が変わります.
PS:コア原理は、反射によってパラメータエンティティ内のフィールドの値を取得し、ルールに従って検証するので、現在はパラメータを含む方法のみをサポートしています.パラメータは基本タイプではありません.
使用spring-bootにおいて、AOPをどのように使用するかについては、ここではもはや説明しない.
Maven依存AOP依存以外に必要な第三者依存は、コアの依存ではなく、個人の習慣によって取捨選択されてもよい.

<dependency>
    <groupId>org.apache.commonsgroupId>
    <artifactId>commons-lang3artifactId>
    <version>3.3.2version>
dependency>


<dependency>
    <groupId>org.slf4jgroupId>
    <artifactId>slf4j-apiartifactId>
    <version>1.7.25version>
dependency>
カスタムコメント
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 *        
 * Created by cipher on 2017/9/20.
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RUNTIME)
public @interface Check {

    //       ,  :   +    +  +    ,  :id<10:ID    10
    String[] value();

}
コアコードspring-bootに注釈されたインターフェース方法を接面ブロックによって加え、方法の実行前にパラメータチェックを行い、エラー情報があれば、直接に返します.
@Around(value = "@com.cipher.checker.Check") //              
public Object check(ProceedingJoinPoint point) throws Throwable {
    Object obj;
    //     
    String msg = doCheck(point);
    if (!StringUtils.isEmpty(msg)) {
        //               
        throw new IllegalArgumentException(msg);
    }
    obj = point.proceed();
    return obj;
}
コアの検証方法は、@Check方法において、注釈上で指定されたフィールド名とチェックルールを取得し、パラメータエンティティに対応するフィールドの値を反射的に取得することによって検証することが主な原理である.
/**
 *     
 *
 * @param point ProceedingJoinPoint
 * @return     
 */
private String doCheck(ProceedingJoinPoint point) {
    //        
    Object[] arguments = point.getArgs();
    //     
    Method method = getMethod(point);
    String methodInfo = StringUtils.isEmpty(method.getName()) ? "" : " while calling " + method.getName();
    String msg = "";
    if (isCheck(method, arguments)) {
        Check annotation = method.getAnnotation(Check.class);
        String[] fields = annotation.value();
        Object vo = arguments[0];
        if (vo == null) {
            msg = "param can not be null";
        } else {
            for (String field : fields) {
                //     
                FieldInfo info = resolveField(field, methodInfo);
                //       
                Object value = ReflectionUtil.invokeGetter(vo, info.field);
                //       
                Boolean isValid = info.optEnum.fun.apply(value, info.operatorNum);
                msg = isValid ? msg : info.innerMsg;
            }
        }
    }
    return msg;
}
主なロジックが見られます.
解析フィールド->フィールドの値を取得します.
内部保守の1つのエニュメレート・クラスは、関連する検査操作はすべて中で指定されています.
/**
 *     
 */
enum Operator {
    /**
     *   
     */
    GREATER_THAN(">", CheckParamAspect::isGreaterThan),
    /**
     *     
     */
    GREATER_THAN_EQUAL(">=", CheckParamAspect::isGreaterThanEqual),
    /**
     *   
     */
    LESS_THAN(", CheckParamAspect::isLessThan),
    /**
     *     
     */
    LESS_THAN_EQUAL("<=", CheckParamAspect::isLessThanEqual),
    /**
     *    
     */
    NOT_EQUAL("!=", CheckParamAspect::isNotEqual),
    /**
     *    
     */
    NOT_NULL("not null", CheckParamAspect::isNotNull);

    private String value;
    private BiFunction fun;

    Operator(String value, BiFunction fun) {
        this.value = value;
        this.fun = fun;
    }
}
紙面の原因のため、ここはすべてのコードを展開しないで、興味がある友達は以下の住所まですべてのソースコードを得ることができます.ciphermagic/java-learn/sadbox/checker
TODO
  • は、Spring Boot Starterとして独立したコンポーネント
  • にパッケージ化されている.
  • 正規表現検証をサポートする
  • 最後に
    読んでくれてありがとうございます.好きな友達はgithubでいいです.何か質問やアドバイスがありましたら、下の方にメッセージを残してください.返事を楽しみにしています.