我正在使用HibernateValidator 4.3.1。验证在整个应用程序中按预期执行。
我已注册了一些自定义编辑器,以便在全局范围内执行验证,例如确保文本字段中的数值(double
,int
等),以确保有关Joda-Time的有效日期API等。
在这种类型的验证中,我通过像往常一样将allowEmpty
参数设置为false
来允许空值/空值,以单独验证它,尤其是当这些字段是显示单独的用户友好错误消息时留空了。
因此,除了使用HibernateValidator和自定义编辑器进行验证之外,我还尝试使用以下验证策略。同样,此类验证仅适用于为自定义编辑器注册的字段在留空时。
以下是实现org.springframework.validation.Validator
接口的类。
package test;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import validatorbeans.TempBean;
@Component
public final class TempValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
System.out.println("supports() invoked.");
return TempBean.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
TempBean tempBean = (TempBean) target;
System.out.println("startDate = " + tempBean.getStartDate() + " validate() invoked.");
System.out.println("doubleValue = " + tempBean.getDoubleValue() + " validate() invoked.");
System.out.println("stringValue = " + tempBean.getStringValue() + " validate() invoked.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startDate", "java.util.date.nullOrEmpty.error");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "doubleValue", "java.lang.double.nullOrEmpty.error");
}
}
使用@Component
注释指定类,以便可以将其自动连接到特定的Spring控制器类。调试语句完全基于用户提供的输入显示。
以下是控制器类。
package controller;
import customizeValidation.CustomizeValidation;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.groups.Default;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import test.TempValidator;
import validatorbeans.TempBean;
@Controller
public final class TempController {
@Autowired
private TempService tempService;
private TempValidator tempValidator;
public TempValidator getTempValidator() {
return tempValidator;
}
@Autowired
public void setTempValidator(TempValidator tempValidator) {
this.tempValidator = tempValidator;
}
@RequestMapping(method = {RequestMethod.GET}, value = {"admin_side/Temp"})
public String showForm(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) {
return "admin_side/Temp";
}
@RequestMapping(method = {RequestMethod.POST}, value = {"admin_side/Temp"})
public String onSubmit(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult errors, Map model, HttpServletRequest request, HttpServletResponse response) {
//tempValidator.supports(TempBean.class);
//tempValidator.validate(tempBean, errors);
DataBinder dataBinder = new DataBinder(tempBean);
dataBinder.setValidator(tempValidator);
dataBinder.validate();
//errors=dataBinder.getBindingResult();
if (CustomizeValidation.isValid(errors, tempBean, TempBean.ValidationGroup.class, Default.class) && !errors.hasErrors()) {
System.out.println("Validated");
}
return "admin_side/Temp";
}
}
我正在通过
从Spring控制器类本身(我确实想要)调用验证器DataBinder dataBinder = new DataBinder(tempBean);
dataBinder.setValidator(tempValidator);
dataBinder.validate();
调用验证器,但预期的验证是不执行。
如果我只使用以下语句(上面已注释掉)手动调用验证器,
tempValidator.validate(tempBean, errors);
然后执行验证。所以我不相信我的验证器正常工作。为什么它无法与DataBinder
一起使用?
在我的application-context.xml
文件中,这个bean的配置简单如下。
<bean id="tempValidator" class="test.TempValidator"/>
以下许多软件包包括test
类所包含的TempValidator
包,都会自动检测到。
<context:component-scan base-package="controller spring.databinder validatorbeans validatorcommands test" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/>
</context:component-scan>
我甚至试图把
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
在我的dispatcher-servlet.xml
文件中。
我在这里俯瞰什么?
答案 0 :(得分:4)
如果我完全理解您尝试实现的目标 - 区分空白字段和输入的错误值 - 您可以使用更多更简单的方法:
public class MyBean {
@NotNull
@DateTimeFormat(pattern="dd.MM.yyyy HH:mm")
private DateTime date;
@NotNull
@Max(value=5)
private Integer max;
@NotNull
@Size(max=20)
private String name;
// getters, setters ...
}
控制器映射:
public void submitForm(@ModelAttribute @Valid MyBean myBean, BindingResult result) {
if (result.hasErrors){
// do something}
else{
// do something else
}
}
验证讯息:
NotNull=Required field.
NotNull.date=Date is required field.
NotNull.max=Max is required field.
Size=Must be between {2} and {1} letters.
Max=Must be lower than {1}.
typeMismatch.java.lang.Integer=Must be number.
typeMismatch.org.joda.time.DateTime=Required format dd.mm.yyyy HH:mm
Spring配置:
@Configuration
public class BaseValidatorConfig {
@Bean
public LocalValidatorFactoryBean getValidator() {
LocalValidatorFactoryBean lvfb = new LocalValidatorFactoryBean();
lvfb.setValidationMessageSource(getValidationMessageSource());
return lvfb;
}
protected MessageSource getValidationMessageSource() {// return you validation messages ...}
}
如果需要,我可以提供更多细节和解释。
答案 1 :(得分:0)
我不知道为什么问题中提到的方法不起作用。我没有让它发挥作用,但走过这个document,我发现另一种方法对我来说符合我的要求。
我将验证器设置在由@InitBinder
注释指定的方法中。
来自docs
当@Valid方法参数为时,调用Validator实例 遇到的可能有两种配置方式。首先,你可以打电话 @ Controller的@InitBinder中的binder.setValidator(Validator) 打回来。这允许您配置Validator实例 @Controller类:
具体来说,在我的要求中,只应在更新数据或将数据插入数据库时执行验证,即按下这些操作的相关提交按钮时(这两个任务都有一个共同的按钮(插入和更新)在我的应用程序中,其名称为btnSubmit
)。
在任何其他情况下(例如,按下删除按钮时)应该静音验证。为了满足这个要求,我已经如下注册了验证器。
@InitBinder
protected void initBinder(WebDataBinder binder, WebRequest webRequest) {
if (webRequest.getParameter("btnSubmit") != null) {
binder.setValidator(new TempValidator());
} else {
binder.setValidator(null);
}
}
在这种情况下,只有在客户点击名称属性为TempValidator
的提交按钮时才会设置验证器 - btnSubmit
。
无需在任何地方进行xml配置以及自动连接。
示例性控制器类现在如下所示。
@Controller
public final class TempController {
@Autowired
private TempService tempService;
@InitBinder
protected void initBinder(WebDataBinder binder, WebRequest webRequest) {
if (webRequest.getParameter("btnSubmit") != null) {
binder.setValidator(new TempValidator());
} else {
binder.setValidator(null);
}
}
//Removed the @Valid annotation before TempBean, since validation is unnecessary on page load.
@RequestMapping(method = {RequestMethod.GET}, value = {"admin_side/Temp"})
public String showForm(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) {
return "admin_side/Temp";
}
@RequestMapping(method = {RequestMethod.POST}, value = {"admin_side/Temp"})
public String onSubmit(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult errors, Map model, HttpServletRequest request, HttpServletResponse response) {
if (CustomizeValidation.isValid(errors, tempBean, TempBean.ValidationGroup.class, Default.class) && !errors.hasErrors()) {
System.out.println("Validated");
}
return "admin_side/Temp";
}
}
WebRequest
方法中的initBinder()
参数不用于处理整个Http请求。它只是用于使用通用请求元数据。
Javadocs关于WebRequest
。
Web请求的通用接口。主要用于通用Web 请求拦截器,让他们访问一般请求元数据, 不是为了实际处理请求。
如果我可能会关注某些错误,请善意澄清或添加其他答案。