我正在开发基本的重置密码流。这是我的dto:
@Getter
@Setter
@FieldsValueMatch(field = "password", fieldMatch = "confirmPassword", message = "Passwords do not match")
public class PasswordResetForm {
@Size(min = 8, message = "Password needs to have at least 8 characters")
private String password;
private String confirmPassword;
}
有 FieldsValueMatch
注解:
@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 {};
}
和验证程序:
public class FieldsValueMatchValidator implements ConstraintValidator<FieldsValueMatch, Object> {
private String field;
private String fieldMatch;
@Override
public void initialize(FieldsValueMatch constraintAnnotation) {
this.field = constraintAnnotation.field();
this.fieldMatch = constraintAnnotation.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;
}
}
}
这是我的控制器:
@Controller
public class ResetPasswordController {
@ModelAttribute("passwordResetForm")
public PasswordResetForm passwordResetForm() {
return new PasswordResetForm();
}
@GetMapping("/reset-password")
public String showResetPasswordForm(final Model model) {
return "reset-password";
}
@PostMapping("/reset-password-result")
public String resetPassword(@Valid final PasswordResetForm passwordResetForm,
final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "reset-password";
}
// reset password logic
return "redirect:/reset-password-success";
}
}
以及thymeleaf页面的一部分:
<form th:action="@{/reset-password-result}" th:object="${passwordResetForm}" method="post">
<div>
<div class="input-group">
<input id="password"
class="form-input"
placeholder="Set a new password"
type="password"
th:field="*{password}"/>
</div>
<div th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></div>
</div>
<div>
<div class="input-group">
<input id="confirmPassword"
class="form-input"
placeholder="Re-type a new password"
type="password"
th:field="*{confirmPassword}"/>
</div>
<div th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}"></div>
</div>
<div class="form-group">
<button type="submit" class="form-btn">SET</button>
</div>
</form>
现在,当我在两个输入中输入不同的密码时,我在终端中得到以下消息:
2021-03-26 11:13:39.315 WARN 1340 [nio-8080-exec-7]
s.w.s.h.AbstractHandlerExceptionResolver : Resolved
[org.springframework.validation.BindException:
org.springframework.validation.BeanPropertyBindingResult: 1 errors
Error in object 'passwordResetForm': codes
[FieldsValueMatch.passwordResetForm,FieldsValueMatch]; arguments
[org.springframework.context.support.DefaultMessageSourceResolvable: codes [passwordResetForm.,]; arguments []; default message [],password,confirmPassword]; default message [Passwords do not match]]
和即时400结果代码。我的 resetPassword
没有调用控制器中的方法,因此取而代之的是我的thymeleaf页,我得到了whitelabel error页。当我把密码短于8个字符时也会发生同样的情况。我做错什么了?
谢谢你的帮助!
4条答案
按热度按时间t98cgbkg1#
你定义
@FieldsValueMatch
作为类级约束。可能是生成的默认约束冲突导致了问题,因为在这种情况下,没有为创建的约束冲突指定显式属性路径。当我把密码短于8个字符时也会发生同样的情况。
不管其他字段级验证(=
@Size
),的@FieldsValueMatch
在任何情况下都会被执行,这可能就是为什么你仍然面临同样的问题。所以,调整
FieldsValueMatchValidator
实现—通过为创建的约束冲突设置属性路径并提供自定义错误消息—应该可以解决问题:kfgdxczn2#
尝试添加
@Validated
上的注解ResetPasswordController
班级(前/后)@Controller
注解)。这应该启用验证bqucvtff3#
检查方法参数序列。
方法参数
你必须申报
Errors
,或BindingResult
参数紧跟在已验证的方法参数之后。所以,如果你的代码看起来像下面这样,你的问题就会重现。
whhtz7ly4#
谢谢你的回复。无缘无故地,它只是开始工作没有任何改变从我这边。。。我不知道发生了什么,也许我需要重新启动我的网络浏览器或类似的东西。。。