英文:
How can a Spring Boot web app validate a form field that is required conditional on another field?
问题
我有一个Spring Boot Web应用程序,在这个应用程序中,我的表单后端Bean的字段被注解为Bean Validation注解(参见Baeldung的教程或spring.io的文档)。例如,Customer bean上的字段可以像这样被注解:
@NotBlank
@Pattern(regexp="[ \\.A-Za-z-]*")
private String firstName;
@DateTimeFormat(pattern="M/d/yyyy")
@NotNull
@Past
private Date DOB;
我想知道的是:我如何实现一个复杂的验证,它涉及多个字段? 我是说,使用这个框架。例如,假设我有一个字段Country
和一个字段ZipCode
,我希望只有当Country
等于"US"
时,ZipCode
才需要@NotBlank
,否则是可选的。
在我的控制器中,验证非常优雅地通过使用@Valid
注解触发,错误会附加到BindingResult
对象上。像这样:
@PostMapping("customer/{id}")
public String updateCustomer(@PathVariable("id") Integer id,
@Valid @ModelAttribute("form") CustomerForm form,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "customerview";
}
customerService.updateCustomer(form);
return "redirect:/customer/" + id;
}
我希望找到的是一种编写这个条件验证器的方式,使它也可以通过@Valid
注解触发,并将其错误消息附加到BindingResult
中的ZipCode
字段。理想情况下,我不应该需要改变控制器代码。
英文:
I have a Spring Boot web app in which fields of my form-backing bean are annotated with Bean Validation annotations (see Baeldung's tutorial or the docs at spring.io). For example, fields on Customer beans might be annotated like this:
@NotBlank
@Pattern(regexp="[ \\.A-Za-z-]*")
private String firstName;
@DateTimeFormat(pattern="M/d/yyyy")
@NotNull
@Past
private Date DOB;
What I want to know is: (How) Can I implement a complex validation that looks at multiple fields? I mean, using this framework. For example, let's say I have a field Country
and a field ZipCode
and I want the ZipCode
to be @NotBlank
if and only if the Country
equals "US"
, optional otherwise.
In my Controller, the validation is very elegantly triggered with the use of the @Valid
annotation, and errors are attached to a BindingResult
object. Like so:
@PostMapping("customer/{id}")
public String updateCustomer( @PathVariable("id") Integer id,
@Valid @ModelAttribute("form") CustomerForm form,
BindingResult bindingResult ) {
if (bindingResult.hasErrors()) {
return "customerview";
}
customerService.updateCustomer(form);
return "redirect:/customer/"+id;
}
What I'm hoping to find is a way to write this conditional validator in a way that it, too, will be triggered by the @Valid
annotation and will attach it's error message to the ZipCode
field in the BindingResult
. Ideally I shouldn't have to change the Controller code at all.
答案1
得分: 1
你可以获取创建自定义验证器类的帮助,以下链接可以帮助您:
https://www.baeldung.com/spring-mvc-custom-validator#custom-validation
英文:
you can getting help of creating custom validator class, the following link helps you:
https://www.baeldung.com/spring-mvc-custom-validator#custom-validation
答案2
得分: 1
对于这种情况,您需要使用交叉字段验证。请尝试:
创建注解:
package foo.bar;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {CustomerValidator.class})
public @interface CustomerValid {
String message() default "{foo.bar.CustomerValid.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
创建自定义验证器:
public class CustomerValidator implements ConstraintValidator<CustomerValid, Customer> {
@Override
public void initialize(CustomerValid constraint) {
}
@Override
public boolean isValid(Customer customer, ConstraintValidatorContext context) {
return !("US".equals(customer.getCountry()) && "".equals(customer.getZipCode()));
}
}
为您的类添加注解:
@CustomerValid
public class Customer {
// 类主体
}
此类验证将与现有字段验证一起进行处理。
英文:
For this kind of stuff you need to use cross field validation. Please try :
Create annotation :
package foo.bar;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {CustomerValidator.class})
public @interface CustomerValid {
String message() default "{foo.bar.CustomerValid.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Create custom validator :
public class CustomerValidator implements ConstraintValidator<CustomerValid, Customer> {
@Override
public void initialize(CustomerValid constraint) {
}
@Override
public boolean isValid(Customer customer, ConstraintValidatorContext context) {
return !("US".equals(customer.getCountry() && "".equals(customer.getZipCode())));
}
}
Annotate your class :
@CustomerValid
public class Customer {
// body
}
This class validation will be processed in addition to existent field validators.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论