【问题标题】:Displaying "Passwords don't match" custom annotation message显示“密码不匹配”自定义注释消息
【发布时间】:2018-04-03 08:18:49
【问题描述】:

如何在 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>

【问题讨论】:

    标签: java spring spring-mvc thymeleaf


    【解决方案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;
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      解决方案是在 HTML 表单中包含全局错误 Thymeleaf syntax。但是由于某种原因,此消息中的单引号:“密码不匹配”,不会被渲染。这个问题的答案是here

      【讨论】:

        猜你喜欢
        • 2022-07-06
        • 1970-01-01
        • 2014-08-11
        • 1970-01-01
        • 2012-10-10
        • 2022-01-10
        • 1970-01-01
        • 2016-01-19
        • 2021-04-04
        相关资源
        最近更新 更多