Spring Boot 는 일반적인 인터페이스 매개 변수 검증 을 실현 합 니 다.

본 고 는 Spring Boot 와 JDK 8 을 바탕 으로 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 주 해 는 인자 AccountVO 의 name,age 속성 이 비어 있 으 면 안 된다 는 것 을 가리 키 고 있 습 니 다.비 어 있 는 검사 외 에 크기 판단,여부 등 검사 도 지원 합 니 다.

@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 를 어떻게 사용 하 는 지 는 더 이상 설명 하지 않 고 AOP 의 핵심 코드 를 소개 합 니 다.
Maven 의존
spring-boot 의존 을 제외 하고 필요 한 제3자 의존 은 핵심 적 인 의존 이 아니 라 개인 습관 에 따라 취사선택 할 수 있 습 니 다.

<!--         -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.3.2</version>
</dependency>

<!--        -->
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.25</version>
</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();

}

핵심 코드
절단면 차단 을 통 해@Check 주해 의 인터페이스 방법 을 추 가 했 습 니 다.방법 이 실행 되 기 전에 매개 변수 검 사 를 실 행 했 습 니 다.잘못된 정보 가 있 으 면 바로 돌아 갑 니 다.

@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;
}
핵심 적 인 검사 방법 은 doCheck 방법 에서 주요 원 리 는 주해 에 지 정 된 필드 이름과 검사 규칙 을 가 져 오고 매개 변수 실체 에 대응 하 는 필드 의 값 을 반사 적 으로 가 져 와 서 검사 하 는 것 입 니 다.

/**
 *     
 *
 * @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;
}
주요 논 리 는:
필드 분석->필드 값 가 져 오기->검사 규칙 실행
내부 유지보수 매 거 진 클래스 입 니 다.관련 검사 작업 은 모두 안에서 지정 합 니 다.

/**
 *     
 */
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<Object, String, Boolean> fun;

  Operator(String value, BiFunction<Object, String, Boolean> fun) {
    this.value = value;
    this.fun = fun;
  }
}

편폭 때문에 여 기 는 모든 코드 를 일일이 펼 치지 않 습 니 다.관심 이 있 는 친 구 는 다음 주소 로 모든 소스 코드 를 얻 을 수 있 습 니 다.ciphermagic/java-learn/sandbox/checker
TODO
  • Spring Boot Starter 방식 으로 독립 구성 요소 로 밀봉
  •  정규 표현 식 검증 지원
  • 마지막.
    읽 어 주 셔 서 감사합니다. 좋아 하 는 친 구 는github에 좋아요 를 누 를 수 있 습 니 다.질문 이 있 거나 아래 에 메 시 지 를 남 겨 주세요.답장 을 기대 하 세 요.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기