복붙노트

[SPRING] 스프링 mvc 중첩 모델 유효성 검사

SPRING

스프링 mvc 중첩 모델 유효성 검사

두 가지 모델이 있습니다 : 사용자, 프로젝트

public class Project{
    private int id;
    @NotEmpty(message="Project Name can not be empty")
    private String name;
    private User manager;
    private User operator;
    //getter/setter omitted
}

public class User{
    private int id;
    private String name;
    //omit other properties and getter/setter
}

이제 새 프로젝트를 만들 때 다음 매개 변수를 ProjectController에 제출합니다.

projects? name = jhon & manager.id = 1 & operator.id = 2 ...

그런 다음 새 Project 객체를 만들어 db에 삽입합니다.

그러나 나는 관리자의 ID를 검증해야하고 연산자는 유효합니다. 즉, 사용자 테이블에 일치하는 ID가 있는지 확인합니다.

그래서 이런 종류의 유효성 검사를 구현하는 방법을 알고 싶습니다.

update1 : 유효성 검사기 사용

이것은 새로운 프로젝트 생성을위한 양식입니다 :

<sf:form method="${project.id==0?'post':'put'}" commandName="project" action="${context}${action}">
    Manager:<sf:input path="manager.id" />  <sf:errors path="manager.id" /> <br />
    Operator:<sf:input path="operator.id" />    <sf:errors path="operator.id" />    <br />
    Name:<sf:input path="name" />   <sf:errors path="name" />   <br />
    <input type="submit" value="Submit" />
</sf:form>


@Override
public void validate(Object obj, Errors errors) {
    User user = (User) obj;
    int id=user.getId();
    User u=userDao.query(id);
    if(u==null){
        errors.rejectValue("id", "user does not exist!");
    }
}

이 유효성 검사기가 작동하는 것 같습니다.

그러나 오류 메시지는 양식에 표시 할 수 없습니다.

그럼 디버그 나는 결과 개체를 검사하고 나는 이것을 발견 :

org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'project' on field 'id': rejected value [0]; codes [user does not exist!.project.id,user does not exist!.id,user does not exist!.int,user does not exist!]; arguments []; default message [null]
Field error in object 'project' on field 'id': rejected value [0]; codes [user does not exist!.project.id,user does not exist!.id,user does not exist!.int,user does not exist!]; arguments []; default message [null]

결과에 오류가있는 것 같지만 경로는 project.id 인 반면 내 양식에서는 project.manager.id입니다.

어떻게 고치는 지?

해결법

  1. ==============================

    1.가능한 해결책은 다음과 같습니다.

    가능한 해결책은 다음과 같습니다.

    아래 클래스를 만듭니다.

    ...
    import org.springframework.validation.Validator;
    ...
    
    @Component
    public class ProjectValidator implements Validator {
    
        @Override
        public boolean supports(Class<?> clazz) {
            return Project.class.equals(clazz);
        }
    
        @Override
        public void validate(Object target, Errors errors) {
            Project project = (Project) target;
    
            /* Do your checks here */
            ...
    
            if (managerIdDoesNotMatch) {
                errors.rejectValue("manager.id", "your_error_code");
            }
    
            ...
    
            if (operatorIdDoesNotMatch) {
                errors.rejectValue("operator.id", "your_error_code");
            }
    
            ...
        }
    }
    

    그리고 컨트롤러에서 다음과 같이하십시오.

    ...
    public class ProjectController {
    
        @Autowired
        ProjectValidator projectValidator;
    
        ...
    
        @RequestMapping(...)
        public String yourCreateMethod(..., @ModelAttribute @Valid Project project, BindingResult result) {
            projectValidator.validate(project, result);           
    
            if (result.hasErrors()){
              // do something
            }
            else {
              // do something else
            }
        }
    
    }
    

    이렇게하면 시작할 수 있습니다. 당신은 인스턴스 생성자 / 유효성 검사기를 다르게 설정할 수 있으며, 사용자 하위 유효성 검사기를 가지고 있지만 일반적인 생각을가집니다.

    참고 문헌 :

  2. ==============================

    2.실제로 필요한 것은 @Valid를 on에 추가하는 것입니다.

    실제로 필요한 것은 @Valid를 on에 추가하는 것입니다.

    private User manager;
    private User operator;
    

    이렇게

    @Valid
    private User manager;
    @Valid
    private User operator;
    
  3. ==============================

    3.컨트롤러에서 사용자 정의 유효성 검사기를 추가 할 수 있습니다.

    컨트롤러에서 사용자 정의 유효성 검사기를 추가 할 수 있습니다.

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(new ProjectValidator());
    }
    

    이 유효성 검사기에서는 6.3 절의 마지막 단락에서 설명한 것처럼 User 객체를 확인하거나 UserValidator에 위임 할 수 있습니다.

  4. ==============================

    4.Jerome Dalbert가 제안한 것 외에 JSR 303 구현에 대한 유효성 검사의 실제 작업을 위임하기위한 사용자 정의 BeanValidator가 추가되었습니다.

    Jerome Dalbert가 제안한 것 외에 JSR 303 구현에 대한 유효성 검사의 실제 작업을 위임하기위한 사용자 정의 BeanValidator가 추가되었습니다.

    접두사는 양식에있는 속성의 경로를 나타내는 데 사용됩니다.

    @Component
    public class BeanValidator implements org.springframework.validation.Validator, InitializingBean {    
    
     private Validator validator;
     public void afterPropertiesSet() throws Exception {
      ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
      validator = validatorFactory.usingContext().getValidator();
     }
    
     public boolean supports(Class clazz) {
      return true;
     }
    
     public void validate(Object target, Errors errors, String prefix) {
      Set<ConstraintViolation<Object>> constraintViolations = validator.validate(target);
      for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
       String propertyPath = constraintViolation.getPropertyPath().toString();
       String message = constraintViolation.getMessage();
       errors.rejectValue(prefix + "." + propertyPath, "", message);
      }
     }
    
     public void validate(Object target, Errors errors) {
      validate(target, errors, "");
     }
    }
    

    UserValidator에서 어떻게 사용했는지 설명합니다.

    @Component
    public class UserValidator implements Validator {
    
     @Autowired
     BeanValidator beanValidator;
    
     @Override
     public boolean supports(Class<?> clazz) {
      return User.class.equals(clazz);
     }
    
     @Override
     public void validate(Object target, Errors errors) {
      User user = (User) target;
      beanValidator.validate(user.getAddress(), errors, "address");
     }
    }
    

    참고 문헌 :

  5. from https://stackoverflow.com/questions/12244639/spring-mvc-nested-model-validation by cc-by-sa and MIT license