显示“密码不匹配”自定义注释消息

时间:2017-10-22 19:27:14

标签: java spring spring-mvc thymeleaf

如何在Spring中将自定义类类型注释中的此消息显示为HTML表单中的警告消息?我正在使用Spring Boot MVC和Thymeleaf。 Thymeleaf可以handle字段错误和全局错误,它们与表单中的任何特定字段无关,但仍然存在。如果此自定义注释发现密码不匹配,则此全局错误或字段错误?我该如何显示此消息?

自定义注释:

@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = PasswordMatchesValidator.class)
@Documented
public @interface PasswordMatches {

    String message() default "Passwords don't match";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

验证员类:

public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, Object> {

    @Override
    public void initialize(PasswordMatches passwordMatches) {
    }

    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext context) {
        UserDto userDto = (UserDto) obj;
        return userDto.getPassword().equals(userDto.getMatchingPassword());
    }
}

后控制器

@PostMapping(value = "/register")
public ModelAndView processRegistration(ModelAndView modelAndView, @Valid @ModelAttribute ("userDto") UserDto userDto,
                                        BindingResult bindingResult, HttpServletRequest request, Errors errors) {
    // Lookup user in database by e-mail
    User userExists = userService.findByEmail(userDto.getEmail());

    System.out.println(userExists);

    if (userExists != null) {
        modelAndView.addObject("alreadyRegisteredMessage", "Oops!  There is already a user registered with the email provided.");
        modelAndView.setViewName("register");
        bindingResult.reject("email");
    }

    if (bindingResult.hasErrors()) {
        modelAndView.setViewName("register");
    } else { // new user so we create user and send confirmation e-mail

        User user = userService.createNewAccount(userDto);
        user.setEnabled(false);
        userService.saveUser(user);

        modelAndView.addObject("confirmationMessage", "A confirmation e-mail has been sent to " + userDto.getEmail());
        modelAndView.setViewName("registered");
    }
}

HTML表单:

<div class="container">
  <div class="row">
    <div class="card col-6 mx-auto" style="width: 20rem; margin: 20px;">
      <div class="card-body">
        <h4 class="card-title">Registration form:</h4>
        <form th:action="@{register}" th:object="${userDto}"  th:method="post" method="post" action="register">
          <div class="form-group">
            <label th:for="name" for="Name">Name</label>
            <input type="text" class="form-control" th:field="*{name}" id="name" placeholder="Enter name">
            <p class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></p>
          </div>
          <div class="form-group">
            <label th:for="surname" for="Surname">Surname</label>
            <input type="text" class="form-control" th:field="*{surname}" id="surname" placeholder="Enter surname">
            <p class="text-danger" th:if="${#fields.hasErrors('surname')}" th:errors="*{surname}"></p>
          </div>
          <div class="form-group">
            <label th:for="username" for="Username">Username</label>
            <input type="text" class="form-control" th:field="*{username}" id="username" placeholder="Enter username">
            <p class="text-danger" th:if="${#fields.hasErrors('username')}" th:errors="*{username}"></p>
          </div>
          <div class="form-group">
            <label th:for="email" for="Email">Email address</label>
            <input type="email" class="form-control" th:field="*{email}" id="email" aria-describedby="emailHelp" placeholder="Enter email">
            <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
            <p class="text-danger"th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></p>
            <p class="text-danger" th:text="${alreadyRegisteredMessage}"></p>
          </div>
          <div class="form-group">
            <label th:for="password" for="Password">Password</label>
            <input type="password" class="form-control" th:field="*{password}" id="password" placeholder="Password">
            <p class="text-danger"th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></p>
          </div>
          <div class="form-group">
            <label th:for="matchingPassword" for="matchingPassword">Confirm Password</label>
            <input type="password" class="form-control" th:field="*{matchingPassword}" id="matchingPassword" placeholder="Password">
            <p class="text-danger"th:if="${#fields.hasErrors('matchingPassword')}" th:errors="*{matchingPassword}"></p>
          </div>
          <button type="submit" class="btn btn-primary">Submit</button>
        </form>
      </div>
    </div>
  </div>
</div>

2 个答案:

答案 0 :(得分:1)

您可以自定义PasswordMatchesValidator类以显示警告消息。

public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, Object> {

  private String message;

    @Override
    public void initialize(PasswordMatches passwordMatches) {
      this.message = passwordMatches.message();
    }

    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext context) {

        final UserDto userDto = (UserDto) obj;
        boolean isValid = userDto.getPassword().equals(userDto.getMatchingPassword());

        if (!isValid) {
            context.disableDefaultConstraintViolation();
            context
                    .buildConstraintViolationWithTemplate( message )
                    .addPropertyNode( "matchingPassword" ).addConstraintViolation();
        }

        return isValid;

    }
}

答案 1 :(得分:0)

解决方案是以HTML格式包含全局错误Thymeleaf syntax。但由于某些原因,此消息中的单引号:&#34;密码不匹配&#34;,不会被渲染。这个问题的答案是here