Car 클래스가 있는데 두 개의 다른 사용자 지정 유효성 검사기에서 순서대로 유효성을 검사하고 싶습니다. 클래스 맨 위에 첫 번째 유효성 검사기를 설정하고 validation-constraints-car.xml 파일에서 다른 유효성 검사기를 설정합니다.
@Validator1
public class Car {
private static final long serialVersionUID = 5535968331666441498L;
...
}
<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
<bean class="com.galery.Car" ignore-annotations="false">
<class ignore-annotations="false">
<constraint annotation="com.galery.validation.specific.Validator2"></constraint>
</class>
</bean>
</constraint-mappings>
첫 번째 유효성 검사기가 실패하면 두 번째 유효성 검사기를 실행하고 싶지 않습니다. 지금은 첫 번째가 실패하더라도 두 번째를 실행하고 두 유효성 검사기 모두에 대한 메시지를 반환합니다. 다음은 내 어노테이션 인터페이스와 컨트롤러 메서드입니다.
@RequestMapping(value = "....", method = RequestMethod.POST)
public void validateCar(@Valid @RequestBody Car car) {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(
validatedBy = {Validator1Impl.class}
)
public @interface Validator1{
String message() default "{validator1.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(
validatedBy = {Validator2Impl.class}
)
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public @interface Validator2{
String message() default "{validator1.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
내가 원하는 것을 어떻게 얻을 수 있습니까? ConstraintValidatorContext에서 이전 유효성 검사기의 메시지를 조회 할 수있는 방법이 있습니까?
@Override
public boolean isValid(Car value, ConstraintValidatorContext context) {
...
}
============================= 올바른 코드
내 코드는 dto "학생"을 사용하여 확인합니다.
학생 dto
@Getter
@Setter
public class Student implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private Integer grade;
}
StudentValidator
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
@Component
public class StudentValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
boolean result = Student.class.equals(clazz);
return result;
}
@Override
public void validate(Object target, Errors errors) {
Student student = (Student) target;
ValidationUtils.rejectIfEmpty(errors, "name","name must not be empty");
}
}
StudentValidator2. 오류가있는 경우 유효성을 검사하지 않습니다.
@Component
public class StudentValidator2 implements Validator {
@Autowired
private MessageSource messageSource;
@Override
public boolean supports(Class<?> clazz) {
boolean result = Student.class.equals(clazz);
return result;
}
@Override
public void validate(Object target, Errors errors) {
if(errors.hasErrors()){
return ;
}
Student student = (Student) target;
if (student.getGrade() <= 0) {
errors.rejectValue("grade", "grade must be more than 0");
}
}
}
StudentController
@RestController("/")
public class StudentController {
@Autowired
private StudentValidator studentValidator;
@Autowired
private StudentValidator2 studentValidator2;
@InitBinder(value = "student")
void initStudentValidator(WebDataBinder binder) {
binder.addValidators(studentValidator, studentValidator2);
}
@PostMapping("/student")
public ResponseEntity<Student> saveStudent(@RequestBody @Valid Student student) {
return new ResponseEntity<>(student, HttpStatus.CREATED);
}
}
postMan을 사용하여 "/ student"에 게시하고 매개 변수가 없습니다. 다음과 같이 응답
{
"status": "BAD_REQUEST",
"error": "Validation failed",
"count": 1,
"errors": [
"name must not be empty"
]
}
===================================== 아래는 옳지 않습니다
WebDataBinder를 사용해야한다고 생각합니다 이를 구현하려면 validate () 메서드를 재정의합니다. 여기에서 참조 하십시오 . 아래는 의사 코드를 제공합니다.
- MyWebDataBinder라는 사용자 지정 WebDataBinder를 만듭니다. 여기서 validate () 메서드를 재정의하십시오.
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
@Component
public class MyWebDataBinder extends WebDataBinder {
public MyWebDataBinder(Object target) {
super(target);
}
public MyWebDataBinder(Object target, String objectName) {
super(target, objectName);
}
@Override
public void validate() {
Object target = getTarget();
Assert.state(target != null, "No target to validate");
BindingResult bindingResult = getBindingResult();
for (Validator validator : getValidators()) {
validator.validate(target, bindingResult);
if(bindingResult.hasErrors())
break;
}
}
}
- 컨트롤러에서 MyWebDataBinder 및 Validator1 및 Validator2를 삽입하십시오.
@Controller
public class CustomerController {
@Autowired
Validator1 validator1
@Autowired
Validator2 validator2
@InitBinder(value = "car")
void initCarValidator(@Qualifier("myWebDataBinder")WebDataBinder binder) {
binder.addValidators(validator1);
binder.addValidators(validator2);
}
@RequestMapping(value = "....", method = RequestMethod.POST)
public void validateCar(@Valid @RequestBody Car car) {
}