尝试在数据库中插入用户时出现错误。
我进行了自定义注释,以验证密码是否与确认密码匹配(当字段不匹配时有效),但是当passowrd匹配时,我出现此错误:
这是我的代码,这是我的字段匹配@Annotation:
package mereuta.marian.tennis01.annotations;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Constraint(validatedBy = FieldsValueMatchValidator.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldsValueMatch {
String message() default "Fields values don't match!";
String field();
String fieldMatch();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@interface List {
FieldsValueMatch[] value();
}
}
这是字段验证器:
package mereuta.marian.tennis01.annotations;
import mereuta.marian.tennis01.model.Utilisateur;
import org.springframework.beans.BeanWrapperImpl;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class FieldsValueMatchValidator implements ConstraintValidator<FieldsValueMatch , Object> {
private String field;
private String fieldMatch;
@Override
public void initialize(FieldsValueMatch fieldsValueMatch) {
this.field=fieldsValueMatch.field();
this.fieldMatch=fieldsValueMatch.fieldMatch();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
Object fieldValue = new BeanWrapperImpl(value)
.getPropertyValue(field);
Object fieldMatchValue = new BeanWrapperImpl(value)
.getPropertyValue(fieldMatch);
if (fieldValue != null) {
return fieldValue.equals(fieldMatchValue);
} else {
return fieldMatchValue == null;
}
}
}
这是我的实体:
@FieldsValueMatch(field = "password", fieldMatch = "confirmPassword",
message = "Password do not match!")
@Entity(name = "utilisateurs")
public class Utilisateur {
@Id @GeneratedValue
@Column(name = "id_utilisateur")
private Integer id;
@NotNull
@Size(min = 4, max = 255)
@Column(name = "password")
private String password;
@Transient
@NotNull
private String confirmPassword;
这是控制器:
@PostMapping("/addUtilisateur")
public String addUtilisateur(@Valid @ModelAttribute("utilisateur") Utilisateur utilisateur, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors() ) {
model.addAttribute("message", "le mot de passe ne correspond pas");
return "utilisateur/formRegister";
}
utilisateurMetier.creerUtilisateur(utilisateur);
return "utilisateur/utilisateurAjoute";
}
最后是View:
<div class="container">
<form id="contact" th:action="@{addUtilisateur}" method="post" th:object="${utilisateur}">
<h3>Créer compte</h3>
<input placeholder="password" type="password" th:field="*{password}" tabindex="2" required/>
<span class="text text-danger" th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span>
</fieldset>
<fieldset>
<input placeholder="password" type="password" th:field="*{confirmPassword}" tabindex="2" required/>
<span class="text text-danger" th:if="${#fields.hasErrors('confirmPassword')}"
th:errors="*{confirmPassword}" th:text="${message}"></span>
</fieldset>
对于自定义注释,我在以下位置找到了一个示例:https://www.baeldung.com/spring-mvc-custom-validator
@Override
public void creerUtilisateur(Utilisateur utilisateur) {
Role role;
float credit = 0;
boolean actif = true;
role = roleRepository.getOne(3);
System.out.println(role);
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
utilisateur.setPassword(encoder.encode(utilisateur.getPassword()));
utilisateur.setRole(role);
utilisateur.setCredit(credit);
utilisateur.setActif(actif);
utilisateurRepository.save(utilisateur);
}
预先感谢您的帮助
答案 0 :(得分:1)
正如已经提到的,ContraintViolationException抛出在'creerUtilisateur'方法内部。因此,当两个字段(密码,confirmPassword)具有相同的值时,在将Utilisateur bean传递给Spring MVC控制器方法(addUtilisateur(@Valid @ModelAttribute("utilisateur")...
)时,其验证就可以正常进行。稍后,您对密码进行编码并更改Utilitsateur的“ password”实例变量的值:
utilisateur.setPassword(encoder.encode(utilisateur.getPassword()));
现在,“ password”和“ passwordConfirm”不再相等!当将此实体持久保存在utilisateurRepository.save(utilisateur);
中时,JPA将再次对您的实体进行bean验证,然后再将其保存到数据库中(预持久化)。当JPA / Hibernate触发预持久,预更新或预删除生命周期事件时,将自动执行验证。然后抛出ContraintViolationException!
在您的creerUtilisateur
方法中,只需为实例变量'password'和'passwordConfirm'设置编码密码,从而确保它们仍通过FieldsValueMatchValidator.isValid(Object value, ConstraintValidatorContext context)
中的相等性检查:
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
final String encodedPassword = encoder.encode(utilisateur.getPassword());
utilisateur.setPassword(encodedPassword);
utilisateur.setPasswordConfirm(encodedPassword);
//...
utilisateurRepository.save(utilisateur);
您还可以尝试自定义JPA的Bean验证行为:
https://www.thoughts-on-java.org/automatically-validate-entities-with-hibernate-validator/