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();
}
}