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
- Spring Mvc那点事---(40)SSM服务框架使用aop进行数据验证
- Spring Mvc那点事---(39)SSM服务框架搭建
- Spring Mvc那点事---(36)rest服务框架搭建
- Spring Mvc那点事---(29)Spring Mvc基于ProxyFactoryBean的传统AOP使用正则拦截
- Spring Mvc那点事---(41)SSM使用log4j2记录日志
- Spring Mvc那点事---(42)SSM使用log4j2记录日志到mysql数据库
- Spring Mvc那点事---(12)Spring Mvc之mybatis使用注解进行增删改查
- Spring Mvc那点事---(26)Spring Mvc基于Schema的AOP实现
- Spring Mvc那点事---(27)Spring Mvc基于aspect的AOP实现
- Spring Mvc那点事---(28)Spring Mvc基于ProxyFactoryBean的传统AOP
- Spring Mvc那点事---(30)Spring Mvc传统AOP自动代理实现
- Spring Mvc那点事---(19)Spring Mvc过滤器Filter实现登陆验证
- Spring Mvc那点事---(33)Spring事务基于AOP实现
- Spring Mvc那点事---(17)Spring Mvc之数据绑定
- Spring mvc 数据验证框架注解
- Spring Mvc那点事---(3)Spring Mvc项目创建
- Spring Mvc那点事---(4)Spring Mvc控制器Controller
- Spring Mvc那点事---(7)Spring Mvc @Autowired注解
- NSRunLoop
- 双11遇上ZBrushCore,如此优惠还等什么!
- C语言常见面试题
- SSL/TLS协议运行机制的概述
- Tinker集成和使用(一)Tinker简介和运行Tinker示例出现的问题
- Spring Mvc那点事---(40)SSM服务框架使用aop进行数据验证
- HashMap循环遍历方式及其性能对比
- 【NOIP%你题】【线性筛】dun题解
- unity 无法使用 dll 库
- sql之left join、right join、inner join的区别
- ScrollView与ListView冲突的问题
- 新浪微博Oauth2.0授权 获取Access Token
- 机器学习笔记-文本专题(TF-IDF)
- How to detect intersection of two faces in 3D