[英]Spring Boot custom validator doesn't return to Controller
我正在開發基本的重置密碼流程。 這是我的 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:
@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 結果代碼。 我在 Controller 中的resetPassword
方法沒有被調用,所以我的 Thymeleaf 頁面得到了 Whitelabel 錯誤頁面。 當我輸入的密碼少於 8 個字符時,也會發生同樣的情況。 我究竟做錯了什么?
感謝您的幫助!
嘗試在ResetPasswordController
class 上添加@Validated
注釋( @Controller
注釋之前/之后)。 這應該啟用驗證
您將@FieldsValueMatch
定義為類級約束。 可能是生成的默認約束違規導致了問題,因為在這種情況下,沒有為創建的約束違規指定顯式屬性路徑。
當我輸入的密碼少於 8 個字符時,也會發生同樣的情況。
無論其他字段級驗證(= @Size
)如何, @FieldsValueMatch
都會在任何情況下執行,這可能就是您仍然面臨同樣問題的原因。
因此,調整FieldsValueMatchValidator
實現 - 通過設置創建的約束違規的屬性路徑並提供自定義錯誤消息 - 應該可以解決問題:
public class FieldsValueMatchValidator implements
ConstraintValidator<FieldsValueMatch, Object> {
// ...
private String message;
@Override
public void initialize(FieldsValueMatch constraintAnnotation) {
// ...
this.message = constraintAnnotation.message();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
//...
boolean valid;
if (fieldValue != null) {
valid = fieldValue.equals(fieldMatchValue);
} else {
valid = fieldMatchValue == null;
}
if (!valid){
context.buildConstraintViolationWithTemplate(this.message) // setting the custom message
.addPropertyNode(this.field) // setting property path
.addConstraintViolation() // creating the new constraint violation
.disableDefaultConstraintViolation() // disabling the default constraint violation
;
}
return valid;
}
}
檢查您的方法 arguments 序列。
您必須在驗證的方法參數之后立即聲明一個
Errors
或BindingResult
參數。
因此,如果您的代碼實際上如下所示,您的問題將被重現。
@PostMapping("/reset-password-result")
public String resetPassword(@Valid PasswordResetForm passwordResetForm, Model model,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "reset-password";
}
// reset password logic
return "redirect:/reset-password-success";
}
感謝所有的答復。 無緣無故,它剛剛開始工作而我沒有任何改變......我不知道發生了什么,也許我需要重新啟動我的 web 瀏覽器或類似的東西......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.