Spring Mvc那点事---(40)SSM服务框架使用aop进行数据验证

来源:互联网 发布:ubuntu 禁止鼠标唤醒 编辑:程序博客网 时间:2024/05/16 11:17

引子

  数据验证是每个系统都经常要做的,大多数情况下,我们是直接在方法里面使用if语句判断是否为空,判断是否是数字类型,判断是否满足条件,如果不满足,就返回客户端错误信息,这样的话,就会显得麻烦,可能同样的判断,在每个方法里面都有写一遍,代码显得臃肿,而且冗余。其实我们有另一种方法进行判断,使用AOP进行拦截,在方法执行前,先把不满足条件的字段进行验证。

准备

    我们使用AOP进行判断,主要的实现思路是结合注解实现,使用注解判断标注要验证的方法,然后使用AOP进行方法参数拦截,在dto对象上标注每个字段需要满足的条件。需要使用如下JAR包validation-api.jar, spring-aop.jar

示例

我们创建一个项目, 首先创建拦截器,拦截器的作用是对方法进行拦截,对方法参数进行校验,这里使用MethodInterceptor环绕通知
package org.supersoft.erp.validation;import java.lang.reflect.Method;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import javax.validation.ConstraintViolation;import javax.validation.Validation;import javax.validation.Validator;import javax.validation.ValidatorFactory;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class ValidationMethodInterceptor implements MethodInterceptor {    /**     * 环绕通知     */    public Object invoke(MethodInvocation invocation) throws Throwable {        Method method = invocation.getMethod();        Object[] arguments = invocation.getArguments();        //判断是否开启校验,凡是标注有@Validatable才开启校验        boolean validation = method.isAnnotationPresent(Validatable.class);        if(!validation) {            //没有开启校验的直接执行            return invocation.proceed();        }        try {            //开启校验后,并且有参数的进行判断            if(arguments != null && arguments.length > 0){                ValidatorFactory factory = Validation.buildDefaultValidatorFactory();                Validator validator = factory.getValidator();                Validatable validatable = method.getAnnotation(Validatable.class);                Class<?>[] groups = validatable.groups();                for(Object argument : arguments){                    Set<ConstraintViolation<Object>> constraintViolations = new HashSet<ConstraintViolation<Object>>();                    System.out.println(argument+"-------");                    if(groups != null && groups.length > 0)                    {                        constraintViolations = validator.validate(argument, groups);                    } else                     {                        constraintViolations = validator.validate(argument);                    }                    if(constraintViolations != null && !constraintViolations.isEmpty())                    {                        for(Iterator<ConstraintViolation<Object>> iterator = constraintViolations.iterator(); iterator.hasNext();)                        {                            String msgKey = iterator.next().getMessage();                            Class<?> clazz = method.getReturnType();                            return clazz.getConstructor(String.class).newInstance(msgKey);                        }                    }                }            }        } catch(NoSuchMethodException e){            System.out.println(method.getReturnType()+ "缺少仅包含一个String变量的构建方法");        } catch (Exception e) {              System.out.println(method.getName()+ "方法参数校验失败!");        }        return invocation.proceed();    }}
添加一个注解,用于标注拦截哪些方法
package org.supersoft.erp.validation;import java.lang.annotation.Retention;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.RetentionPolicy.RUNTIME;@Target({ METHOD})@Retention(RUNTIME)public @interface Validatable {    Class<?>[] groups() default {};}

接下来建立几个接口,用于操作分组,标注某个字段在执行什么操作的时候进行判断,比如同一个字段,有的时候需要在创建的时候进行判断,有点需要在更新的时候进行判断,
package org.supersoft.erp.validation;public interface Create {}package org.supersoft.erp.validation;public interface Retrieve {}package org.supersoft.erp.validation;public interface Delete {}package org.supersoft.erp.validation;public interface Update {}


验证规则

org.hibernate.validator.constraints包下面有许多定义好的验证注解规则,可以直接标注在字段上,@NotBlank判断是否为空,@NotNull判断是否为null,引入hibernate-validator-5.3.0.Final.jar
<dependency>                <groupId>org.hibernate</groupId>                <artifactId>hibernate-validator</artifactId>                <version>5.3.0.Final</version>            </dependency>
创建一个dto对象
package org.supersoft.erp.rest.dto;import javax.validation.constraints.NotNull;import org.hibernate.validator.constraints.Length;import org.hibernate.validator.constraints.NotBlank;import org.supersoft.erp.validation.Create;import org.supersoft.erp.validation.Delete;import org.supersoft.erp.validation.Retrieve;import org.supersoft.erp.validation.Update;public class ProductDto {    public final static String CODE_REQUIRED = "code-required";    public final static String SCOPE_REQUIRED = "scope-required";    public final static String SCOPE_LENGTH = "scope-length-30";    public final static String CODE_LENGTH = "code-length-30";    public final static String NAME_REQUIRED = "name-required";    public final static String NAME_LENGTH = "name-length-30";    //编码不能为空,并且长度最大30    @NotBlank(message = CODE_REQUIRED, groups = { Update.class, Retrieve.class, Delete.class })    @Length(message = SCOPE_LENGTH, max = 30)  private String code;    //名称不能为空     @NotNull(message = NAME_REQUIRED, groups = { Create.class, Update.class })      private String name;      private String color;    public String getCode() {        return code;    }    public void setCode(String code) {        this.code = code;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getColor() {        return color;    }    public void setColor(String color) {        this.color = color;    }}
使用验证注解,将验证注解标注在方法上,并配置spring.aop
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns:context="http://www.springframework.org/schema/context"    xmlns:aop="http://www.springframework.org/schema/aop"    xsi:schemaLocation="     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">    <bean id="validationMethodInterceptor" class="org.supersoft.erp.validation.ValidationMethodInterceptor">    </bean>    <aop:config proxy-target-class="true">        <aop:pointcut id="restMethodPointcut" expression="execution(* org.supersoft.erp.rest..*.*(..))" />        <aop:advisor pointcut-ref="restMethodPointcut" advice-ref="validationMethodInterceptor" />    </aop:config> </beans>
标注方法
   * 修改     */    @RequestMapping(value = "update", method = RequestMethod.POST)    @ResponseBody    @Validatable(groups = { Update.class })    public CommonResponse<?> updateProduct(@RequestBody ProductDto product) {        try        {            Product p=new Product();            BeanUtils.copyProperties(product, p);            productService.updateProduct(p);            return CommonResponse.result();        }        catch(Throwable t)        {            return CommonResponse.error();        }    }

然后,我们启动程序,就可以进行验证了

demo下载 http://download.csdn.net/detail/zx13525079024/9677511

0 0
原创粉丝点击