1、切面依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、工具类

/**
* @author LiuHuan
* @date 2019-11-14 21:07
* @desc 切面工具
*/
public class AspectUtil { /**
* 参数校验
* @param args
* @param method
*/
public static List<String> checkParam(Object[] args, Method method){
List<String> errorMsgList = Lists.newArrayList();
if (null == args || 0 == args.length || null == method) {
return errorMsgList;
} Annotation[][] parameterAnnotations = method.getParameterAnnotations(); int index = 0;
for (Annotation[] parameterAnnotation : parameterAnnotations) {
Object arg = args[index++];
for (Annotation annotation : parameterAnnotation) {
if (annotation instanceof NotNull) {
if (null == arg) {
NotNull notNull = (NotNull)annotation;
errorMsgList.add(notNull.name() + notNull.msg());
}
} else if (annotation instanceof NotEmpty) {
if (checkArgEmpty(arg)) {
NotEmpty notEmpty = (NotEmpty)annotation;
errorMsgList.add(notEmpty.name() + notEmpty.msg());
}
} else if (annotation instanceof VerifyBean) {
errorMsgList.addAll(checkBean(arg,((VerifyBean)annotation)));
}
}
} return errorMsgList; } /**
* 校验参数是否为empty
* @param arg
* @return
*/
private static boolean checkArgEmpty(Object arg) {
return null == arg || arg instanceof String && ((String)arg).isEmpty() ||
arg instanceof Collection && ((Collection)arg).isEmpty() ||
arg instanceof Map && ((Map)arg).isEmpty();
} /**
* 校验bean属性参数合法性
* @param bean
* @param verifyBean
* @return
*/
private static List<String> checkBean(Object bean, VerifyBean verifyBean) {
List<String> errorMsg = Lists.newArrayList();
if (null == bean) {
errorMsg.add(verifyBean.name() + verifyBean.msg());
return errorMsg;
} List<Field> fields = getFields(bean.getClass()); //校验bean中的每个参数合法性
for (Field field : fields) {
Annotation[] annotations = field.getDeclaredAnnotations();
if (null == annotations || 0 == annotations.length) {
continue;
} field.setAccessible(true);
Object value = null;
try {
value = field.get(bean);
} catch (IllegalAccessException e) {
//异常不做处理,取null
} for (Annotation annotation : annotations) {
if (annotation instanceof NotNull && checkNotNull((NotNull)annotation,verifyBean.type(),value)) {
NotNull notNull = (NotNull)annotation;
errorMsg.add(field.getName() + notNull.msg());
} else if (annotation instanceof NotEmpty && checkNotEmpty((NotEmpty)annotation,verifyBean.type(),value)) {
NotEmpty notEmpty = (NotEmpty)annotation;
errorMsg.add(field.getName() + notEmpty.msg());
}
} } return errorMsg; } /**
* 判断在请求类型相符的情况下参数是否为空
* @param annotation
* @param type
* @param value
* @return
*/
private static boolean checkNotEmpty(NotEmpty annotation, ServiceTypeEnum type, Object value) {
for (ServiceTypeEnum serviceTypeEnum : annotation.type()) {
if (serviceTypeEnum.equals(type) || serviceTypeEnum.equals(ServiceTypeEnum.ALL)) {
return checkArgEmpty(value);
}
}
return false;
} /**
* 判断在请求类型相符的情况下参数是否为null
* @param annotation
* @param type
* @param value
* @return
*/
private static boolean checkNotNull(NotNull annotation, ServiceTypeEnum type, Object value) {
for (ServiceTypeEnum serviceTypeEnum : annotation.type()) {
if (serviceTypeEnum.equals(type) || serviceTypeEnum.equals(ServiceTypeEnum.ALL)) {
return null == value;
}
}
return false;
} /**
* 获取该类所有属性
* @param clazz
* @return
*/
private static List<Field> getFields(Class<?> clazz) {
List<Field> fields = Lists.newArrayList(); //获取父类属性
Class<?> superclass = clazz.getSuperclass();
if (null != superclass) {
List<Field> supperFields = getFields(superclass);
fields.addAll(supperFields);
} Field[] declaredFields = clazz.getDeclaredFields();
fields.addAll(Arrays.asList(declaredFields));
return fields;
}
}

3、切面

/**
* @author LiuHuan
* @date 2019-11-14 21:15
* @desc 数据校验切面
*/
@Component
@Aspect
public class RequestParamAspect { private static Logger logger = LoggerFactory.getLogger(RequestParamAspect.class); @Pointcut("execution(* com.cainiao.finance.customer.facade.api.*.*(..))")
public void serviceBefore(){} /**
* 方法执行前校验参数合法性
* @param point
*/
@Before("serviceBefore()")
public void before(JoinPoint point){
Method method = ((MethodSignature)point.getSignature()).getMethod();
List<String> errorList = AspectUtil.checkParam(point.getArgs(), method);
if (!errorList.isEmpty()) {
logger.error("{}#{} param invalid, reason:{}",method.getDeclaringClass().getSimpleName(), method.getName(), errorList.toString());
throw new ParamException(errorList);
}
}
}

4、注解

/**
* @author LiuHuan
* @date 2019-11-14 21:06
* @desc 字段非空校验
*/
@Target(value = {ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmpty { ServiceTypeEnum[] type() default {ServiceTypeEnum.ALL}; /**
* 参数名
* @return
*/
String name() default ""; /**
* 报错信息
* @return
*/
String msg() default "不能为空"; } /**
* @author LiuHuan
* @date 2019-11-14 21:06
* @desc 字段非null校验
*/
@Target(value = {ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotNull { ServiceTypeEnum[] type() default {ServiceTypeEnum.ALL}; /**
* 参数名
* @return
*/
String name() default ""; /**
* 报错信息
* @return
*/
String msg() default "不能为空";
} /**
* @author LiuHuan
* @date 2019-11-14 21:06
* @desc bean校验
*/
@Target(value = {ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface VerifyBean { /**
* 校验类型
* @return
*/
ServiceTypeEnum type() default ServiceTypeEnum.ALL; /**
* 参数名
* @return
*/
String name(); /**
* 报错信息
* @return
*/
String msg() default "不能为空";
}

5、枚举

/**
* @author LiuHuan
* @date 2019-11-14 21:52
* @desc 请求类型枚举
*/
public enum ServiceTypeEnum { /**
* 所有
*/
ALL,
/**
* 新增
*/
INSERT,
/**
* 删除
*/
DELETE,
/**
* 修改
*/
UPDATE }

6、异常

/**
* @author LiuHuan
* @date 2019-11-15 10:03
* @desc 参数异常
*/
public class ParamException extends RuntimeException{ private List<String> errorList; public ParamException(List<String> errorList) {
this.errorList = errorList;
} public List<String> getErrorList() {
return errorList;
} public void setErrorList(List<String> errorList) {
this.errorList = errorList;
} @Override
public String getMessage() {
return errorList.toString();
}
}

AOP参数校验的更多相关文章

  1. springboot学习-jdbc操作数据库--yml注意事项--controller接受参数以及参数校验--异常统一管理以及aop的使用---整合mybatis---swagger2构建api文档---jpa访问数据库及page进行分页---整合redis---定时任务

    springboot学习-jdbc操作数据库--yml注意事项--controller接受参数以及参数校验-- 异常统一管理以及aop的使用---整合mybatis---swagger2构建api文档 ...

  2. springmvc 参数校验/aop失效/@PathVariable 参数为空

    添加依赖 <!-- 参数校验 --> <dependency> <groupId>org.hibernate.validator</groupId> & ...

  3. springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版)

    一.引入相应的maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifa ...

  4. 利用Aspectj实现Oval的自动参数校验

    前言: Oval参数校验框架确实小巧而强大, 他通过注解的方式配置类属性, 然后通过Oval本身自带的工具类, 快速便捷执行参数校验. 但是工具类的校验需要额外的代码编写, 同时Oval对函数参数级的 ...

  5. springboot 参数校验详解

    https://www.jianshu.com/p/89a675b7c900 在日常开发写rest接口时,接口参数校验这一部分是必须的,但是如果全部用代码去做,显得十分麻烦,spring也提供了这部分 ...

  6. SpringBoot 参数校验的方法

    Introduction 有参数传递的地方都少不了参数校验.在web开发中,前端的参数校验是为了用户体验,后端的参数校验是为了安全.试想一下,如果在controller层中没有经过任何校验的参数通过s ...

  7. Spring Boot 之:接口参数校验

    Spring Boot 之:接口参数校验,学习资料 网址 SpringBoot(八) JSR-303 数据验证(写的比较好) https://qq343509740.gitee.io/2018/07/ ...

  8. Spring Boot实现通用的接口参数校验

    Spring Boot实现通用的接口参数校验 Harries Blog™ 2018-05-10 2418 阅读 http ACE Spring App API https AOP apache IDE ...

  9. SpringMVC参数校验,包括JavaBean和基本类型的校验

    该示例项目使用SpringBoot,添加web和aop依赖. SpringMVC最常用的校验是对一个javaBean的校验,默认使用hibernate-validator校验框架.而网上对校验单个参数 ...

随机推荐

  1. mysql索引类型:FULLTEXT、NORMAL、SPATIAL、UNIQUE的区别

    1. Normal 普通索引 2. Unique 唯一索引 3. Full Text 全文索引 4. SPATIAL 空间索引 5. btree索引和hash索引的区别 6. 在实际操作过程中,应该选 ...

  2. 第 1 篇 Scrum 冲刺博客(5.21)

    一.Alpha阶段认领的任务 二.明日任务安排 成员 5.22任务安排 工时 陈芝敏 调用小程序接口获取用户微信登录权限,初始化 1h 在页面显示倒计时 5h 冯晓凤 继续学习微信开放文档 5h 江晓 ...

  3. classmethod与staticmethod

    1.classmethod   @classmethod # 把一个对象绑定的方法 修改成一个 类方法第一,在方法中仍然可以引用类中的静态变量第二,可以不用实例化对象,就直接用类名在外部调用这个方法什 ...

  4. Django万能权限框架组件

    业务场景分析 假设我们在开发一个培训机构的 客户关系管理系统,系统分客户管理.学员管理.教学管理3个大模块,每个模块大体功能如下 客户管理 销售人员可以录入客户信息,对客户进行跟踪,为客户办理报名手续 ...

  5. 2020.08.14小bug

    页面下面的滚动条怎么清除 css overflow-x: hidden;

  6. 2020,你需掌握go 单元测试进阶篇

    本文说明go语言自带的测试框架未提供或者未方便地提供的测试方案,主要是用于解决写单元测试中比较头痛的依赖问题.也就是伪造模式,经典的伪造模式有桩对象(stub),模拟对象(mock)和伪对象(fake ...

  7. Shader 语义

    在书写HLSL shader程序时,输入和输出变量需要拥有他们 含义来表明语义.这在HLSL shader中是一个标准的做法. Vertex shader 输入语义 主顶点着色器函数(被指令 #pra ...

  8. SpringMVC实例及注解(二)

    @RequestMapping()除了修饰方法,还可以修饰类1.类定义处:提供初步的请求映射信息.相对于WEB应用的根目录2.方法处:提供进一步的细分映射信息.相对于类定义处的URL.若类定义处未标注 ...

  9. dom:文档对象模型,提供的api去操作页面上的元素

    dom对象通过html标签转义成了文档操作对象

  10. [LeetCode]面试题14- I. 剪绳子(DP/贪心)

    题目 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m.n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m] .请问 k[0]k[1]...* ...