Как проверить мою регистрационную форму в thymeleaf?

#java #spring-boot #validation #error-handling #thymeleaf

#java #spring-boot #проверка #обработка ошибок #thymeleaf

Вопрос:

Я создаю небольшой api с Spring Boot, Spring Security, Thymeleaf. Я создал рабочий логин, роли безопасности и теперь пытаюсь выполнить регистрацию. Если я добавлю новые (правильные для моей базы данных) данные, то пользователь будет создан правильно, однако я выполнил некоторые классические проверки в CrmUser, такие как @Notnull и мои собственные — проверки электронной почты и сопоставление паролей. Все они не работают. Я не знаю почему. Единственное, что работает, это «имя пользователя уже существует» из моего метода контроллера. Кто-нибудь может помочь?

 import com.marcinha.stylist.validation.FieldMatch;
import com.marcinha.stylist.validation.ValidEmail;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@FieldMatch.List({
        @FieldMatch(first = "password", second = "matchingPassword", message = "The password fields must match")
})
public class CrmUser {

    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String userName;

    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String password;

    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String matchingPassword;

    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String firstName;

    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String lastName;

    @ValidEmail
    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String email;

    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String country;

    public CrmUser() {
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getMatchingPassword() {
        return matchingPassword;
    }

    public void setMatchingPassword(String matchingPassword) {
        this.matchingPassword = matchingPassword;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EmailValidator implements ConstraintValidator<ValidEmail, String> {

    private Pattern pattern;
    private Matcher theMatcher;
    private final static String EMAIL_PATTERN = "^[_A-Za-z0-9-\\ ] (\\.[_A-Za-z0-9-] )*@"n"  
            "ttt  "[A-Za-z0-9-] (\\.[A-Za-z0-9] )*(\\.[A-Za-z]{2,})$";

    @Override
    public boolean isValid(String email, ConstraintValidatorContext constraintValidatorContext) {

        pattern = Pattern.compile(EMAIL_PATTERN);

        if (email == null) {
            return false;
        }
        theMatcher = pattern.matcher(email);
        return theMatcher.matches();


    }
}

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Constraint(validatedBy = EmailValidator.class)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidEmail {

    String message() default "Invalid email";

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

}

import org.springframework.beans.BeanWrapperImpl;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> {


    private String firstFieldName;
    private String secondFieldName;
    private String message;

    @Override
    public void initialize(FieldMatch constraintAnnotation) {
        firstFieldName = constraintAnnotation.first();
        secondFieldName = constraintAnnotation.second();
        message = constraintAnnotation.message();
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {

        boolean valid = true;
        try{

              Object firstObj = new BeanWrapperImpl(o).getPropertyValue(firstFieldName);
              Object secondObj = new BeanWrapperImpl(o).getPropertyValue(secondFieldName);

              valid = firstObj == null amp;amp; secondObj == null || firstObj != null amp;amp; secondObj.equals(firstObj);
        }
        catch (Exception ignore){

        }

        if(!valid){
            constraintValidatorContext.buildConstraintViolationWithTemplate(message)
                    .addPropertyNode(firstFieldName)
                    .addConstraintViolation()
                    .disableDefaultConstraintViolation();
        }
        return valid;
    }
}

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = FieldMatchValidator.class)
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldMatch {

    String message() default "";

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

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

    String first();

    String second();

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
        FieldMatch[] value();
    }

}

@Controller
@RequestMapping("/registry")
public class RegistrationController {

    @Autowired
    private UserService service;

    private Logger logger = Logger.getLogger(getClass().getName());


    @GetMapping("/showRegistrationForm")
    public String showRegistration(Model model) {

        model.addAttribute("crmUser", new CrmUser());

        return "registration-from";
    }


    @PostMapping("/processingRegistrationForm")
    public String registry(@Valid @ModelAttribute("crmUser") CrmUser theCrmUser,
                           BindingResult theBindingResult,
                           Model theModel) {
        String username = theCrmUser.getUserName();
        logger.info("Processing registration form for: "   username);

        if (theBindingResult.hasErrors()) {
            return "registration-form";
        }

        User existingUser = service.findByUserName(username);
        if (existingUser != null) {
            theModel.addAttribute("crmUser", new CrmUser());
            theModel.addAttribute("registrationError", "User already exist in database");

            logger.warning("User name already exists.");


            return "registration-form";
        }

        service.save(theCrmUser);

        logger.info("Successfully created user: "   username);

        return "registration-confirmation";
    }
}

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
    <Title> Registration form </Title>

    <link rel="stylesheet"
          href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

</head>


<body>

<form th:action="@{/registry/processingRegistrationForm}"
      th:object="${crmUser}" method="POST">

    <!-- Check for registration error -->
    <div th:if="${registrationError}">
        <span th:text="${registrationError}"></span>
    </div>

    <!-- User name -->
    <div>
        <input type="text" th:field="*{userName}" placeholder="Username (*)">
    </div>
    <div th:if="${#fields.hasErrors('userName')}">
        <ul>
            <li th:each="err : ${#fields.errors('userName')}" th:text="'User name '   ${err}" />
        </ul>
    </div>

    <!-- Password -->
    <div>
        <input type="password" th:field="*{password}" placeholder="Password (*)">
    </div>
    <div th:if="${#fields.hasErrors('password')}">
        <ul>
            <li th:each="err : ${#fields.errors('password')}" th:text="'Password '   ${err}" />
        </ul>
    </div>

    <!-- Confirm Password -->
    <div>
        <input type="password" th:field="*{matchingPassword}" placeholder="confirm password (*)">
    </div>
    <div th:if="${#fields.hasErrors('matchingPassword')}">
        <ul>
            <li th:each="err : ${#fields.errors('matchingPassword')}" th:text="'Password '   ${err}" />
        </ul>
    </div>

    <!--First Name -->
    <div>
        <input type="text" th:field="*{firstName}" placeholder="First name (*)">
    </div>
    <div th:if="${#fields.hasErrors('firstName')}">
        <ul>
            <li th:each="err : ${#fields.errors('firstName')}" th:text="'First name '   ${err}" />
        </ul>
    </div>


    <!-- Last Name -->
    <div>
        <input type="text" th:field="*{lastName}" placeholder="Last name (*)">
    </div>
    <div th:if="${#fields.hasErrors('lastName')}">
        <ul>
            <li th:each="err : ${#fields.errors('lastName')}" th:text="'Last name '   ${err}" />
        </ul>
    </div>

    <!-- Email -->
    <div>
        <input type="text" th:field="*{email}" placeholder="Email (*)">
    </div>
    <div th:if="${#fields.hasErrors('email')}">
        <ul>
            <li th:each="err : ${#fields.errors('email')}" th:text="'Email '   ${err}" />
        </ul>
    </div>



    <!-- Register Button -->
    <div class="col-sm-6 controls">
        <button type="submit" class="btn btn-primary">Register</button>
    </div>
</form>


</body>
</html>
 

Ответ №1:

Неважно: D Я пропустил одну зависимость в моем pom:

  <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>