在 Spring MVC 中使用 JSR-303 注释进行条件验证
Using JSR-303 annotations for conditional validation in Spring MVC
我有一个包含十个字段的表单,但页面最初只显示五个字段。其余字段被隐藏,并根据绑定到其他字段的 onChange 事件侦听器显示。
在某些情况下,可以提交只有五个非空白字段的表单。在这种情况下,只需对这五个进行验证。有时,必须对所有字段执行验证(基于具有 onChange 回调的其他字段的状态)。有没有一种方法可以使用注释来过滤字段验证,或者我应该编写一个自定义验证器?
现在所有十个表单字段都已验证。
规则如下:
- a,b,c,d,e 为必填字段
- f,g,h 仅在 a="111" 时出现
- i,j 仅在 c="222" 时出现
示例代码:
@NotBlank
private String a;
@NotBlank
private String b;
@NotBlank
private String c;
@NotBlank
private String d;
@NotBlank
private String e;
@NotBlank(a="111")
private String f;
@NotBlank(a="111")
private String g;
@NotBlank(a="111")
private String h;
@NotBlank(c="222")
private String i;
@NotBlank(c="222")
private String j;
控制器代码:
@RequestMapping(value="/payments/getTax.do", method=RequestMethod.POST)
public String getTaxInfo(@Valid OneTimeForm command, BindingResult result,
Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {
OneTimeForm oneTimeForm = (OneTimeForm) command;
try {
validator.validate(oneTimeForm, result);
} catch (ValidationException ex) {
throw ex;
}
...///
您应该能够 运行 手动验证器并过滤掉您不想 return 给客户端的错误。
为了能够手动执行验证器,我必须添加 BindingResult 作为 rest 方法实现的参数。没有 BindingResult Spring 框架没有调用方法,但 return 向客户端发送了验证错误。
@RequestMapping(method = PATCH, value = "/{id}")
public ResponseEntity<User> patchUser(@RequestBody User patchUser,
BindingResult bindingResult) {
如果你描述一下你的控制器,我可以提供更准确的答案。
感谢您提供更多详细信息。
在我的解决方案中,我从控制器定义中删除了 @Valid 注释,因此我有空的 bindingResult。然后我以编程方式验证并找出我想要 return 给客户端的验证错误。
BindingResult allErrors = new BeanPropertyBindingResult(target, objectName);
//validate and copy relevant errors into bindingResult
validator.validate(target, allErrors);
for (FieldError fe : allErrors.getFieldErrors()) {
if (/* your conditions */) {
bindingResult.addError(fe);
}
}
我可以建议两种方法。
您可以创建小模型并对其进行验证。验证成功后,您将构建您的实体。
或者您可以创建自己的验证约束并验证整个 class onSubmit。
您可以通过 Bean Validation 注释来验证必填字段,但对于更复杂的条件逻辑(即 f,g,h show up only if a="111" and i,j show up only if c="222"
),有 org.springframework.validation.Validator
。
您的示例实施可以是:
public class OneTimeFormValidator implements org.springframework.validation.Validator {
@Override
public boolean supports(Class clazz) {
return OneTimeForm.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
final OneTimeForm form = (OneTimeForm) target;
if ("111".equals(form.getA())) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "f", "f.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "g", "g.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "h", "h.required");
}
if ("222".equals(form.getC())) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "i", "i.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "j", "j.required");
}
}
}
ValidationUtils.rejectIfEmptyOrWhitespace(Errors, String, String)
与 @NotBlank
行为相同。因此不要注释可选字段:
@NotBlank
private String a;
@NotBlank
private String b;
@NotBlank
private String c;
@NotBlank
private String d;
@NotBlank
private String e;
private String f;
private String g;
private String h;
private String i;
private String j;
您的控制器可能看起来像:
...
@Autowired
private org.springframework.validation.Validator oneTimeFormValidator;
@RequestMapping(value="/payments/getTax.do", method=RequestMethod.POST)
public String getTaxInfo(@Valid OneTimeForm command, BindingResult result) {
// validates conditional logic with OneTimeFormValidator
oneTimeFormValidator.validate(command, result);
if (result.hasErrors()) {
// return a page
}
// do something else and return a page
}
...
必填字段使用提供的 javax.validation.Validator
到 @Valid
类型的实例进行验证。遇到的验证错误被放入 BindingResult
实例中。然后通过OneTimeFormValidator
进行条件验证,遇到的验证错误放入BindingResult
.
同一个实例中
使用验证组,
定义两组 https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#chapter-groups
我有一个包含十个字段的表单,但页面最初只显示五个字段。其余字段被隐藏,并根据绑定到其他字段的 onChange 事件侦听器显示。
在某些情况下,可以提交只有五个非空白字段的表单。在这种情况下,只需对这五个进行验证。有时,必须对所有字段执行验证(基于具有 onChange 回调的其他字段的状态)。有没有一种方法可以使用注释来过滤字段验证,或者我应该编写一个自定义验证器?
现在所有十个表单字段都已验证。 规则如下:
- a,b,c,d,e 为必填字段
- f,g,h 仅在 a="111" 时出现
- i,j 仅在 c="222" 时出现
示例代码:
@NotBlank
private String a;
@NotBlank
private String b;
@NotBlank
private String c;
@NotBlank
private String d;
@NotBlank
private String e;
@NotBlank(a="111")
private String f;
@NotBlank(a="111")
private String g;
@NotBlank(a="111")
private String h;
@NotBlank(c="222")
private String i;
@NotBlank(c="222")
private String j;
控制器代码:
@RequestMapping(value="/payments/getTax.do", method=RequestMethod.POST)
public String getTaxInfo(@Valid OneTimeForm command, BindingResult result,
Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {
OneTimeForm oneTimeForm = (OneTimeForm) command;
try {
validator.validate(oneTimeForm, result);
} catch (ValidationException ex) {
throw ex;
}
...///
您应该能够 运行 手动验证器并过滤掉您不想 return 给客户端的错误。 为了能够手动执行验证器,我必须添加 BindingResult 作为 rest 方法实现的参数。没有 BindingResult Spring 框架没有调用方法,但 return 向客户端发送了验证错误。
@RequestMapping(method = PATCH, value = "/{id}")
public ResponseEntity<User> patchUser(@RequestBody User patchUser,
BindingResult bindingResult) {
如果你描述一下你的控制器,我可以提供更准确的答案。
感谢您提供更多详细信息。 在我的解决方案中,我从控制器定义中删除了 @Valid 注释,因此我有空的 bindingResult。然后我以编程方式验证并找出我想要 return 给客户端的验证错误。
BindingResult allErrors = new BeanPropertyBindingResult(target, objectName);
//validate and copy relevant errors into bindingResult
validator.validate(target, allErrors);
for (FieldError fe : allErrors.getFieldErrors()) {
if (/* your conditions */) {
bindingResult.addError(fe);
}
}
我可以建议两种方法。
您可以创建小模型并对其进行验证。验证成功后,您将构建您的实体。
或者您可以创建自己的验证约束并验证整个 class onSubmit。
您可以通过 Bean Validation 注释来验证必填字段,但对于更复杂的条件逻辑(即 f,g,h show up only if a="111" and i,j show up only if c="222"
),有 org.springframework.validation.Validator
。
您的示例实施可以是:
public class OneTimeFormValidator implements org.springframework.validation.Validator {
@Override
public boolean supports(Class clazz) {
return OneTimeForm.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
final OneTimeForm form = (OneTimeForm) target;
if ("111".equals(form.getA())) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "f", "f.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "g", "g.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "h", "h.required");
}
if ("222".equals(form.getC())) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "i", "i.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "j", "j.required");
}
}
}
ValidationUtils.rejectIfEmptyOrWhitespace(Errors, String, String)
与 @NotBlank
行为相同。因此不要注释可选字段:
@NotBlank
private String a;
@NotBlank
private String b;
@NotBlank
private String c;
@NotBlank
private String d;
@NotBlank
private String e;
private String f;
private String g;
private String h;
private String i;
private String j;
您的控制器可能看起来像:
...
@Autowired
private org.springframework.validation.Validator oneTimeFormValidator;
@RequestMapping(value="/payments/getTax.do", method=RequestMethod.POST)
public String getTaxInfo(@Valid OneTimeForm command, BindingResult result) {
// validates conditional logic with OneTimeFormValidator
oneTimeFormValidator.validate(command, result);
if (result.hasErrors()) {
// return a page
}
// do something else and return a page
}
...
必填字段使用提供的 javax.validation.Validator
到 @Valid
类型的实例进行验证。遇到的验证错误被放入 BindingResult
实例中。然后通过OneTimeFormValidator
进行条件验证,遇到的验证错误放入BindingResult
.
使用验证组, 定义两组 https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#chapter-groups