vaidate 주 해 를 검사 합 니 다.
이전에 도 hibenate 의 검증 주 해 를 사용 한 적 이 있 지만 정 리 를 하지 않 았 습 니 다.여기 서 블 로 그 를 참고 하여 정 리 를 하 겠 습 니 다.JSR 303/JSR-349,hibenate vaidation,spring vaidation 간 의 관 계 를 약술 합 니 다.JSR 303 은 표준 입 니 다.JSR-349 는 업그레이드 버 전 입 니 다.새로운 기능 을 추 가 했 습 니 다.그들 은 일부 검증 규범 즉 검증 주 해 를 규정 합 니 다.예 를 들 어@Null,@NotNull,@Pattern 은 자바 x.vaidation.constraints 가방 에 있 고 규범 만 제공 하고 실현 되 지 않 습 니 다.한편,hibenate vaidation 은 이 규범 에 대한 실천(hibenate 와 데이터베이스 orm 프레임 워 크 를 연결 하지 마 십시오)입 니 다.그 는 해당 하 는 실현 을 제공 하고 다른 검증 주 해 를 추 가 했 습 니 다.예 를 들 어@Email,@Length,@Range 등 은 org.hibenate.vaidator.constraints 가방 에 있 습 니 다.한편,만능 spring 은 개발 자 에 게 편리 함 을 제공 하기 위해 hibenate vaidation 을 2 차 로 패 키 징 했 습 니 다.검증 vaidated bean 을 표시 할 때 spring vaidation 이나 hibenate vaidation 을 사용 할 수 있 습 니 다.spring vaidation 의 또 다른 기능 은 springmvc 모델 에 자동 검증 을 추가 하고 검증 정 보 를 특정한 클래스 에 패키지 하 는 것 입 니 다.이것 은 의심 할 여지없이 우리 의 웹 개발 을 편리 하 게 했다.본 고 는 주로 springmvc 에서 자동 으로 검사 하 는 메커니즘 을 소개 한다.
도입 의존
우리 가 구축 한 것 은 spring boot 프로젝트 이기 때문에 웹 의 starter 의존 도 를 직접 도입 하면 됩 니 다.
org.springframework.boot
spring-boot-starter-web
자식 의존 도 를 보면 다음 과 같은 의존 도 를 발견 할 수 있 습 니 다.
org.hibernate
hibernate-validator
com.fasterxml.jackson.core
jackson-databind
검사 하 다
검 증 된 실체 클래스
여기에 lombok 의@Data 주 해 를 사 용 했 고 여러분 이 사용 하 는 플러그 인 을 매우 추천 합 니 다.
@Data
public class ValidateBO {
@NotBlank(message = "name ")
private String name;
@Min(value = 18, message = " 18 ")
private Integer age;
@Email(message = "email ")
private String email;
/**
*
*/
@CannotHaveBlank
private String blank;
/**
*
*/
@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$", message = " ")
private String phone;
}
여기 서 흔히 볼 수 있 는 주 해 를 사용 한 것 을 볼 수 있다.사용자 정의 검사 주 해 는 아래 에서 언급 합 니 다)
컨트롤 러 검사
controller 에서 이 필드 의 검 사 를 진행 하면 검사 해 야 할 대상 마다 BindingResult 가 검사 결 과 를 받 아야 하고 검사 할 클래스 에@Validated 주 해 를 추가 해 야 합 니 다.
@GetMapping(value = "/validate")
public String validate(ValidateBO validateBO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
StringBuilder stringBuilder = new StringBuilder();
for (String s : bindingResult.getFieldErrors().stream()
.map(FieldError::getDefaultMessage).collect(Collectors.toList())) {
stringBuilder.append(s);
}
return stringBuilder.toString();
}
return "success";
}
항목 을 시작 하고 url 에 항목 에 debug 를 입력 하 십시오.첫 번 째 필드 가 요구 에 부합 되 지 않 으 면 오 류 를 직접 되 돌려 주 는 것 이 아니 라 모든 검사 필드 를 검사 하 는 것 을 볼 수 있 습 니 다.물론 이것 도 설정 할 수 있 습 니 다.아래 에 fast-fail 설정 이 언급 되 어 있 습 니 다.마지막 으로 돌아 온 결과:이 대상 의 모든 오 류 를 인쇄 한 것 입 니 다.
일반적인 검사 주해
JSR 에서 제공 하 는 검사 설명:
@Null null
@NotNull null
@AssertTrue true
@AssertFalse false
@Min(value) ,
@Max(value) ,
@DecimalMin(value) ,
@DecimalMax(value) ,
@Size(max=, min=)
@Digits (integer, fraction) ,
@Past
@Future
@Pattern(regex=,flag=)
Hibernate Validator 가 제공 하 는 검사 설명:
@NotBlank(message =) null, 0
@Email
@Length(min=,max=)
@NotEmpty
@Range(min=,max=,message=)
그룹 검사
장면
같은 클래스 가 있 으 면 서로 다른 사용 장면 에서 서로 다른 검사 규칙 이 있 으 면 그룹 검 사 를 사용 할 수 있 습 니 다.미성년 자 는 술 을 마 시 면 안 되 고 다른 장면 에서 우 리 는 특별한 제한 을 하지 않 는 다.이 수 요 는 어떻게 같은 실체,서로 다른 검사 규칙 을 나타 내 는가?
검사 대상
@Data
public class ValidateByGroupBO {
/**
* adult validate
*/
@Min(value = 18, groups = {Adult.class})
private Integer age;
public interface Adult{}
public interface Minor{}
}
성인 그룹 에서 만 최소 값 18 의 검 사 를 할 수 있 도록 정의 합 니 다.
검증 을 진행 하 다
/**
* , adult
* @param validateByGroupBO
* @param bindingResult
* @return
*/
@GetMapping(value = "/drink")
public String drink(@Validated({ValidateByGroupBO.Adult.class}) ValidateByGroupBO validateByGroupBO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
//
return "false";
}
return "success";
}
/**
* adult age
* @param validateByGroupBO
* @param bindingResult
* @return
*/
@GetMapping(value = "live")
public String live(@Validated ValidateByGroupBO validateByGroupBO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
//
return "false";
}
return "success";
}
실행 후 url 에 입력http://localhost:7001/drink?age=10첫 번 째 는 false 로 돌아 갑 니 다.그 중의 Adult 그룹 을 지정 하면 age 에 대한 검 사 를 시작 합 니 다.입력http://localhost:7001/live?age=10age 의 크기 를 검사 하지 않 고 success 로 돌아 갑 니 다.술 을 마 실 때 는 성인 여 부 를 검증 하고 생활 을 하지 않 아 도 비슷 한 장면 은 쉽게 만 날 수 있다.
사용자 정의 주석
주 해 를 실현 하 다
빈 칸 을 포함 할 수 없 는 문자열 을 만 듭 니 다.주로 두 단계 로 나 뉜 다.
4.567917.이 주 해 를 먼저 정의 합 니 다.그 중에서 vaidated By 는 진정 으로 검 사 를 하 는 실체 류 를 지정 합 니 다.그 중 groups 와 payload 는 기본 값 으로 사용 할 수 있 습 니 다
@Target({METHOD, FIELD, ANNOTATION_TYPE, ElementType.CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
//
@Constraint(validatedBy = {CannotHaveBlankValidator.class})
public @interface CannotHaveBlank {
//
String message() default " ";
//
Class>[] groups() default {};
//
Class extends Payload>[] payload() default {};
//
@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
@interface List {
CannotHaveBlank[] value();
}
}
4.567917.두 번 째 단 계 는 진정 으로 검 사 를 하 는 실체 류 를 실현 하 는 것 이다
public class CannotHaveBlankValidator implements ConstraintValidator {
@Override
public void initialize(CannotHaveBlank cannotHaveBlank) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//null
if (value != null && value.contains(" ")) {
//
String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate();
System.out.println("default message :" + defaultConstraintMessageTemplate);
//
context.disableDefaultConstraintViolation();
//
context.buildConstraintViolationWithTemplate("can not contains blank")
.addConstraintViolation();
return false;
}
return true;
}
}
이 인 터 페 이 스 는 ConstraintValidator 인 터 페 이 스 를 실현 합 니 다.이 인터페이스 에는 이벤트 초기 화 방법 과 합 법 여 부 를 판단 하 는 방법 이 포함 되 어 있 습 니 다.
package javax.validation;
import java.lang.annotation.Annotation;
public interface ConstraintValidator{
void initialize(A var1);
boolean isValid(T var1, ConstraintValidatorContext var2);
}
그 중의 A 범 형 매개 변 수 는 이전 단계 에 정 의 된 주해 류 이 고 범 형 T 는 검증 할 필드 형식 입 니 다.ConstraintValidatorContext 이 매개 변수 컨 텍스트 는 인증 에 있 는 모든 정 보 를 포함 하고 있 습 니 다.저 희 는 이 컨 텍스트 를 이용 하여 기본 오류 알림 정 보 를 얻 고 오류 알림 정 보 를 사용 하지 않 으 며 오류 알림 정 보 를 바 꾸 는 등 작업 을 할 수 있 습 니 다.
사용자 정의 주석 검사
이 사용자 정의 주 해 를 첫 번 째 controller 로 검증 하 는 것 이 좋 습 니 다.검사 할 대상 에 사용자 정의 주해 의 blank 필드 가 추가 되 었 기 때 문 입 니 다.시작 항목,입력http://localhost:7001/validate?blank=19 209(여기에 빈 칸 을 넣 었 습 니 다).반환 값 은 사용자 정의 주석 이 작용 했다 는 것 을 알 수 있 습 니 다.
@Valid 와@Validated 의 차이
https://blog.csdn.net/qq_27680317/article/details/79970590 이 편 은 매우 분명하게 말 했다.
aop
분명히 우리 모든 controller 의 방법 이 Binding Result 를 쓰 면 매우 번 거 로 워 집 니 다.사실은 우 리 는 매개 변 수 를 검사 하고 log 에 출력 해 야 합 니 다.그러면 자 연 스 럽 게 op 이 생각 납 니 다.
주해 표식
주 해 를 정의 하여 표 지 를 표시 합 니 다.hibenate vaidate 주 해 를 사 용 했 습 니 다.
package com.zhanglijun.springbootdemo.domain.anno;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.groups.Default;
/**
* hibernate
* @author
* @create 2018/8/19 22:28
*/
@Target({ElementType.METHOD,ElementType.TYPE,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableValidate {
Class> [] groups() default { Default.class };//
}
정의 절단면
package com.zhanglijun.springbootdemo.aspect;
import com.zhanglijun.springbootdemo.domain.anno.EnableValidate;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.executable.ExecutableValidator;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.hibernate.validator.HibernateValidator;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
/**
* @author
* @create 2018/8/19 18:45
*/
@Slf4j
@Aspect
@Component
public class ValidatorAspect {
/**
*
*/
private static final Validator validator = Validation.byProvider(HibernateValidator.class)
.configure()
// ,
.failFast(true)
.buildValidatorFactory().getValidator();
/**
* point
*/
@Pointcut("execution(* com.zhanglijun.springbootdemo.web.controller..*.*(..))")
public void pointcut() {
}
/**
* @desction: 1. Hibernate validator , 2. EgValidate , , Bean ,
* 3. ( )( 、 ) EgValidate , EgValidate , , Bean ,
* @author: wangji
* @date: 2018/3/13 10:16
*/
@Before("pointcut()")
public void before(JoinPoint point) {
//
Object target = point.getThis();
//
Object[] args = point.getArgs();
//
Method method = ((MethodSignature) point.getSignature()).getMethod();
Annotation[] classAnnotations = target.getClass().getAnnotations();
Annotation[] methodAnnotations = method.getAnnotations();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
// , Hibernate validator
if (parameterAnnotations != null) {
validMethodParams(target, method, args);
}
// EgValidate , ,Bean
int i = 0;
//
Set idSet = new HashSet<>(3);
for (Object arg : args) {
if (arg != null) {
if (parameterAnnotations != null) {
for (Annotation parameterAnnotation : parameterAnnotations[i]) {
if (parameterAnnotation instanceof EnableValidate) {
if (!ClassUtils.isPrimitiveOrWrapper(arg.getClass())) {
validBeanParam(arg,
((EnableValidate) parameterAnnotation).groups());
idSet.add(i);
}
}
}
}
i++;
}
}
//
EnableValidate egValidate = null;
//
if (methodAnnotations != null) {
egValidate = AnnotationUtils.findAnnotation(method, EnableValidate.class);
}
//
if (egValidate == null && classAnnotations != null) {
egValidate = AnnotationUtils.findAnnotation(target.getClass(), EnableValidate.class);
}
// , , ,
if (egValidate != null && args != null && args.length > 0) {
i = 0;
for (Object arg : args) {
if (arg != null && !ClassUtils.isPrimitiveOrWrapper(arg.getClass()) && !idSet
.contains(i)) {
validBeanParam(arg, egValidate.groups());
}
i++;
}
}
}
/**
* @param obj Bean
* @param groups
* @desction: Bean
* @author: wangji
* @date: 2018/3/13 10:10
*/
private void validBeanParam(Object obj, Class>... groups) {
Set> validResult = validator.validate(obj, groups);
throwConstraintViolationException(validResult);
}
/**
* @param obj
* @param method
* @param params
* @desction: Hibernate Bean 【 User getUserInfoById(@NotNull(message =
* " ") Integer id);】
* @author: wangji
* @date: 2018/3/13 10:11
*/
private void validMethodParams(Object obj, Method method, Object[] params) {
ExecutableValidator validatorParam = validator.forExecutables();
Set> validResult = validatorParam
.validateParameters(obj, method, params);
throwConstraintViolationException(validResult);
}
/**
* @desction:
* @author: wangji
* @date: 2018/3/13 10:09
*/
private void throwConstraintViolationException(Set> validResult) {
if (!validResult.isEmpty()) {
throw new ConstraintViolationException(validResult.iterator().next().getMessage(),
validResult);
}
}
}
이 절단면 도 매우 제거 되 어 여러 곳 에서 이 곳 을 사용 하 는 곳 에 대해 검 사 를 하 였 다.
github
위 코드 는 모두 제 github 에 있 습 니 다.코드 를 리 뷰 할 수 있 습 니 다.validated 주석 관련
인용 하 다.
참고 블 로그:
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.