【问题标题】:Validation does not work on nested objects验证不适用于嵌套对象
【发布时间】:2017-09-29 08:11:18
【问题描述】:

我试图通过将请求参数直接绑定到用户实体来简化我的代码,而不是逐个字段地复制值,但我似乎无法以这种方式进行验证。

控制器:

    @Autowired
    private UserValidator validator;

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

    @PreAuthorize("isAnonymous()")
    @RequestMapping("/register")
    public List<String> register(@Valid @ModelAttribute RegisterRequest request, BindingResult result){
        return result.getAllErrors().stream().map(error -> error.getCodes()[1]).collect(Collectors.toList());
    }

验证器:

@Component
public class UserValidator implements Validator {

    @Autowired
    private UserRepository repo;

    @Override
    public boolean supports(Class<?> clazz) {
        return clazz.equals(RegisterRequest.class)||clazz.equals(User.class);
    }

    @Override
    public void validate(Object target, Errors errors) {
        if(target instanceof RegisterRequest){
            RegisterRequest request = (RegisterRequest)target;
            if(isRegistered(request))
                errors.rejectValue("User.Email", "InUse");
            if(!isRepassCorrect(request))
                errors.rejectValue("Repassword", "NoMatch");
        }

    }

    private boolean isRegistered(RegisterRequest request){
        return repo.findByEmail(request.getUser().getEmail())!=null;
    }

    private boolean isRepassCorrect(RegisterRequest request){
        return request.getPassword().equals(request.getRepassword());
    }

}

模型(注意嵌套对象用@Valid注解):

public class RegisterRequest {

    @Valid
    private User user = new User();

    @NotEmpty
    private String password;

    @NotEmpty
    private String repassword;

    //Generated getters and setters for all fields

}

@Entity
@Table(name = "users")
public class User implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 3726459440738726042L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @NotEmpty
    @Email
    @Column(name = "email", nullable = false)
    private String email;

    @NotEmpty
    @Column(name = "hash", nullable = false)
    private String hash;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(referencedColumnName = "id")
    private UserRole role;

    @Column(name = "enabled", nullable = false)
    private boolean enabled;

    @NotEmpty
    @Column(name = "name", nullable = false)
    private String name;

    @Column(name = "company")
    private String company;

    //Getters, setters, equals and hashCode

}

问题是只有密码和重新密码字段被正确验证,用户类中的验证注释被忽略,任何只有匹配密码的请求都会通过,而它应该会出现错误。空密码或不同密码会按预期出现错误。

【问题讨论】:

  • 当然不行。您注册了一个禁用 JSR-330 验证的自定义验证器。而不是setValidator 使用addValidator。
  • 就是这样。添加验证器而不是替换它按预期工作。非常感谢。

标签: spring spring-mvc


【解决方案1】:

在你 initBinder 中使用 addValidator 方法而不是 setValidator 并通过在注释中添加 MaV 名称来告诉它要验证哪个 MaV 对象:

@InitBinder("request")

和

... @Valid @ModelAttribute("request") RegisterRequest request

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 2018-02-27
    • 1970-01-01
    相关资源
    最近更新 更多