Spring Validator方法级别的参数校验,方法界别参数校验的全局处理,Sping MVC使用Hibernate Validator,自定义校验器

来源:互联网 发布:qq群淘宝优惠券的阴谋 编辑:程序博客网 时间:2024/06/17 11:18

参考文档: http://docs.spring.io/spring/docs/4.2.9.RELEASE/spring-framework-reference/htmlsingle/#validation-beanvalidation

Spring 3介绍了对其验证支持的几种增强。首先,JSR-303 Bean验证API现在完全支持,when used programmatically, Spring’s DataBinder can now validate objects as well as bind to them. Third, Spring MVC now has support for declaratively validating @Controller inputs.当使用编程方式实现的时候也是支持,对于控制层的输入.

JSR-303规范java平台的验证约束声明和元数据。使用此API,您用声明性验证约束注释域模型属性,运行时强制执行它们。有一些内置的限制,您可以利用。您还可以定义自己的自定义约束。之前已经有了简单的介绍。当类的实例由JSR-303验证器验证时,这些约束将被强制执行。

由之前的Hibernate Validate的使用可以简单的看到,我们需要校验器

对于spring来说,我们需要将校验器注入成为Bean的对象,然后方便我们在任何的地方进行使用。pring provides full support for the Bean Validation API. This includes convenient support for bootstrapping(引导) a JSR-303/JSR-349 Bean Validation provider as a Spring bean. This allows for a javax.validation.ValidatorFactory or javax.validation.Validator to be injected wherever validation is needed in your application.Use the LocalValidatorFactoryBean to configure a default Validator as a Spring bean:他会自己去找JSR-300的实现的

<bean id="validator"    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

上面的基本配置将触发bean验证,使用它的默认引导机制初始化。jsr-349 JSR-303 /供应商,如Hibernate Validator,有望在类路径中的呈现,将自动检测。

注入校验器

LocalValidatorFactoryBean implements both javax.validation.ValidatorFactory and javax.validation.Validator, as well as Spring’s org.springframework.validation.Validator. You may inject a reference to either of these interfaces into beans that need to invoke validation logic.Inject a reference to javax.validation.Validator if you prefer to work with the Bean Validation API directly:(通过注入可以直接的操作相应的API进行使用)如果你想用spring的ValidatorAPI注入的时候自己选择就好了。
下面这个是使用的spring的Validator。其实差不多,看你自己喜欢使用哪个API,在spring MvC中一会会有例子的。

public interface Validator {    /**     * Validate the supplied {@code target} object, which must be     * of a {@link Class} for which the {@link #supports(Class)} method     * typically has (or would) return {@code true}.     * <p>The supplied {@link Errors errors} instance can be used to report     * any resulting validation errors.     * @param target the object that is to be validated (can be {@code null})     * @param errors contextual state about the validation process (never {@code null})     * @see ValidationUtils     */    void validate(Object target, Errors errors);}

注入很简单,可以注入校验器或者约束工厂

@Service@Slf4jpublic class UserInfoService implements IUserInfoService {    @Autowired    private Validator validator;}

在spring 中自定义校验器(Configuring Custom Constraints)

package com.common.utils.Hibernatevalidatedemo.spring;import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by wangji on 2017/8/12. */@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = customeValidate.class)//处理的类public @interface GenderAnnotation {    String message() default "必须是女人";    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {};    Gender value() default Gender.Neutrality;}** * descrption: 男女 * authohr: wangji * date: 2017-08-12 15:33 */public enum Gender {    Woman("女人",1),    Man("男人",2),    Neutrality("中立",3);    private String F;    private Integer value;    Gender(String f, Integer value) {        F = f;        this.value = value;    }    public String getF() {        return F;    }    public void setF(String f) {        F = f;    }    public Integer getValue() {        return value;    }    public void setValue(Integer value) {        this.value = value;    }}

必须为女人的约束类的实现(在spring 中你可以注入Bean就像Aware一样他会主动发现的)

package com.common.utils.Hibernatevalidatedemo.spring;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;/** * descrption: spring中自定义约束其 * authohr: wangji * date: 2017-08-12 15:26 */public class customeValidate implements ConstraintValidator<GenderAnnotation,Gender>{    //As you can see, a ConstraintValidator implementation may have its dependencies @Autowired like any other Spring bean.    //在spring 你可以直接在这里面注入@Resource 自己需要的Bean处理器    Gender value;    public void initialize(GenderAnnotation constraintAnnotation) {        value= constraintAnnotation.value();//获取注解的值    }    public boolean isValid(Gender value, ConstraintValidatorContext context) {        if(!(value instanceof  Gender) || value ==null){            return false;        }else{            if(value.getValue().equals(2) || value.getValue().equals(3)){                return false;            }            return true;//必须是女的        }    }}

测试:

public class Person {    @GenderAnnotation(message = "必须是女人")    private Gender gender;    private Integer age;    public Gender getGender() {        return gender;    }    ...}import javax.validation.ConstraintViolation;import javax.validation.Validation;import javax.validation.Validator;import javax.validation.ValidatorFactory;import java.util.Set;/** * descrption: 自定义鉴别器测试 * authohr: wangji * date: 2017-08-12 15:48 */@Slf4jpublic class GenderTest {    public static void main(String[] args) {        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();        Validator validator = validatorFactory.getValidator();       Person person = new Person();       person.setGender(Gender.Man);       pringValidateStr(validator.validate(person));    }    public static void pringValidateStr(Set<ConstraintViolation<Person>> set2) {        for (ConstraintViolation<Person> constraintViolation : set2){            log.info("错误:" + constraintViolation.getMessage());            log.info("字段:"+constraintViolation.getPropertyPath().toString());        }    }}2017-08-12 15:55:44,764  INFO [Version.java:30] : HV000001: Hibernate Validator 5.4.0.Final2017-08-12 15:55:45,062  INFO [GenderTest.java:27] : 错误:必须是女人2017-08-12 15:55:45,063  INFO [GenderTest.java:28] : 字段:gender

Spring-driven Method Validation(方法级别的弹簧式驱动验证,自主的选择)验证器

The method validation feature supported by Bean Validation 1.1, and as a custom extension also by Hibernate Validator 4.3, can be integrated into a Spring context through a MethodValidationPostProcessor bean definition:

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

In order to be eligible for Spring-driven method validation, all target classes need to be annotated with Spring’s @Validated annotation, optionally declaring the validation groups to use. (意思就是可以验证方法界别的啦)
譬如下面的这个方法,你只需要在他的类上添加 @Validated注解,然后就可以在调用方法后捕获到异常,你可以是当前直接捕获异常,或者全局异常处理器去捕获异常的信息。

 @NotNull(message = "返回值不能为空")  public User getUserInfoById(@NotNull(message = "不能为空") Integer id,String message);

譬如:捕获这个异常ConstraintViolationException,在全局的异常处理函数中去处理。

if(e instanceof ConstraintViolationException){            Set<ConstraintViolation< ?>> constraintViolations = ((ConstraintViolationException) e).getConstraintViolations();            for(ConstraintViolation item : constraintViolations){                log.info("Item:"+item.getPropertyPath().toString()+"  message:"+item.getMessage());            }}

Configuring a DataBinder

Since Spring 3, a DataBinder instance can be configured with a Validator. Once configured, the Validator may be invoked by calling binder.validate(). Any validation Errors are automatically added to the binder’s BindingResult.
When working with the DataBinder programmatically, this can be used to invoke validation logic after binding to a target object:

Foo target = new Foo();DataBinder binder = new DataBinder(target);binder.setValidator(new FooValidator());// bind to the target objectbinder.bind(propertyValues);// validate the target objectbinder.validate();// get BindingResult that includes any validation errorsBindingResult results = binder.getBindingResult();

A DataBinder can also be configured with multiple Validator instances via dataBinder.addValidators and dataBinder.replaceValidators. This is useful when combining globally configured Bean Validation with a Spring Validator configured locally on a DataBinder instance.(这个数据绑定就是,spring mvc校验使用的处理流程)

在User这个JavaBean中定制了一些错误的提示,这里的Errors就是因为SPring给我们进行了处理,将处理的结果赋值到了errors中去了,他的实现类似BindingResult,OK?

 @RequestMapping("/error")    @ResponseBody    public ActionResult saveUser(@Valid User user, Errors errors) {        ActionResult result = new ActionResult(true);        if (errors.hasErrors()) {            List<FieldError> list = errors.getFieldErrors();            for(FieldError error :list){                log.info(error.getField());                log.info(error.getCode());                log.info(error.getDefaultMessage());            }            result.setData(errors.getFieldErrors());        }        return result;    }

一般情况都是使用默认Hibernate Validator,你也可以添加自定义的Validator

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:mvc="http://www.springframework.org/schema/mvc"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/mvc        http://www.springframework.org/schema/mvc/spring-mvc.xsd">    <mvc:annotation-driven validator="globalValidator"/></beans>

To combine global with local validation, simply add one or more local validator(s):

@Controllerpublic class MyController {    @InitBinder    protected void initBinder(WebDataBinder binder) {        binder.addValidators(new FooValidator());    }}

With this minimal configuration any time an @Valid or @Validated method argument is encountered, it will be validated by the configured validators. Any validation violations will automatically be exposed as errors in the BindingResult accessible as a method argument and also renderable in Spring MVC HTML views.

全局异常处理,处理对于spring对于方法级别参数校验的错误的情况

可以做你任何想做的事情。

package com.common.utils;import lombok.extern.slf4j.Slf4j;import org.springframework.validation.FieldError;import org.springframework.web.servlet.HandlerExceptionResolver;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.view.json.MappingJackson2JsonView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.validation.ConstraintViolation;import javax.validation.ConstraintViolationException;import java.util.List;import java.util.Set;/** * descrption: 全局异常处理 * authohr: wangji * date: 2017-08-01 8:54 */@Slf4jpublic class GlobalHandlerExceptionResolver implements HandlerExceptionResolver {    private MappingJackson2JsonView  jsonView = new MappingJackson2JsonView();    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {        ModelAndView modelAndView = new ModelAndView();        modelAndView.setView(jsonView);        modelAndView.addObject("error",e.getMessage());        if(e instanceof ConstraintViolationException){            Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) e).getConstraintViolations();            for(ConstraintViolation item : constraintViolations){                log.info("Item:"+item.getPropertyPath().toString()+"  message:"+item.getMessage());            }        }        modelAndView.addObject("result",false);        return modelAndView;    }}
阅读全文
1 0
原创粉丝点击