Spring Boot + Thymeleaf - 表单验证

Jan*_*wak 5 spring thymeleaf

我在验证表单时遇到 Thymeleaf 问题。我正在尝试创建简单的用户注册表来学习 Spring,但不幸的是我被卡住了。

这是我的 UserForm 类

public class UserForm {
    @NotEmpty
    private String username;
    @NotEmpty
    private String password;
    @NotEmpty
    private String passwordConfirm;

    \\ Getters and Setters
}
Run Code Online (Sandbox Code Playgroud)

第一个问题是当我在 initBinder 中添加我的自定义验证器类时

@Autowired
private UserFormValidator formValidator;

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setValidator(formValidator);
}
Run Code Online (Sandbox Code Playgroud)

@NotEmpty验证注释的“默认”停止工作。这是预期的行为?

第二个问题是如何在百里香叶中显示全局拒绝消息?
我的验证器类如下所示

public class UserFormValidator implements Validator {
    @Autowired
    UserService userService;

    @Override
    public boolean supports(Class<?> clazz) {
        return UserForm.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        UserForm userForm = (UserForm) target;
        if(!userForm.getPassword().equals(userForm.getPasswordConfirm())) {
            errors.reject("passwords.no.match", "Passwords not match");
        }

        if(userService.findOneByUsername(userForm.getUsername()).isPresent()) {
            errors.reject("user.exist", "User already exists (default)");
        }
    }   
}
Run Code Online (Sandbox Code Playgroud)

并从控制器发布映射

@PostMapping("/create")
public String registerUser(@ModelAttribute("form") @Valid final UserForm form, BindingResult bindingResult) {
    if(bindingResult.hasErrors()) {
        return "newuser";
    }
    userService.saveUser(form);
    return "redirect:/";
}
Run Code Online (Sandbox Code Playgroud)

作为“默认”验证错误,我可以使用 ex th:if="${#fields.hasErrors('passwordConfirm')}" 显示我不知道如何显示错误passwords.no.match 的消息或检查是否存在发生了错误?

Mon*_*mul 6

默认情况下,spring boot 使用 bean 验证来验证用 @Valid 注释的表单对象。如果您想使用自定义验证器并通过@InitBinder 注册它,则不会进行 bean 验证,这是预期的行为。如果您希望 bean 验证也适用于您的自定义验证,您需要在验证器类中甚至在控制器中手动进行。

这是显示密码不匹配错误消息的第二个问题。在您的自定义验证器 UserFormValidator.class 中,同时拒绝您需要使用 rejectValue() 方法的任何值,如下所示:

    @Override
    public void validate(Object target, Errors errors) {
        UserForm userForm = (UserForm) target;
        if(!userForm.getPassword().equals(userForm.getPasswordConfirm())) {
            errors.rejectValue("passwordConfirm", "passwords.no.match", "Passwords not match");
        }

        if(userService.findOneByUsername(userForm.getUsername()).isPresent()) {
            errors.rejectValue("username", "user.exist", "User already exists (default)");
        }
    } 
Run Code Online (Sandbox Code Playgroud)

rejectValue() 方法用于向 Errors 对象添加验证错误。第一个参数标识错误与哪个字段相关联。第二个参数是一个错误代码,它作为messages.properties 文件(或messages_en.properties 或messages_fr.properties 等,如果它们正在被使用)的消息键。rejectValue() 的第三个参数表示回退默认消息,如果在资源包中找不到匹配的错误代码,则显示该消息。

现在您可以th:if="${#fields.hasErrors('passwordConfirm')}在表单内使用显示错误消息。