使用Spring AOP、自定义注解实现对Request传参拦截

使用Spring boot开发项目与前端人员对接接口时由于在调试,经常传来null、undefined、NaN等非法参数,于是利用spring 的自定义注解以及AOP实现简单的传入参数拦截。

一、使用方法

    /**
     * 登录
     * 当参数是实体类时,通过 参数名.属性名 的方式注解参数
     */
    @ArgsNotNull({"user.stuNo", "user.password"})
    @PostMapping("login.do")
    public ServerResponse login(User user) {
        //To do Login
        return ServerResponse.createBySuccess();
    }
    /**
     * 通过userId查询
     * 当参数是基本类时,通过 参数名 的方式注解参数
     */
    @ArgsNotNull({"userId"})
    @GetMapping("findByUserId.do")
    public ServerResponse findByUserId(String userId) {
        //To do findByUserId
       return ServerResponse.createBySuccess();
    }

二、构建方法
1、添加Spring AOP pom依赖

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
    </dependency>

2、自定义参数检查类

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 检查参数注解
 *
 * @author chenyi
 * Create on 2019/10/13
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ArgsNotNull {
    /**
     * 拦截字段
     */
    String[] value() default {};
}

3.AOP类,拦截使用了@ArgsNotNull 注解的方法

/**
 * 参数检验aop
 *
 * @author chenyi
 * Create on 2019/10/13
 */
@Aspect
@Component
public class ArgsNotNullAop {
    /**
     * 检查参数是否为空
     */
    @Around("@annotation(ArgsNotNull)")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //拦截的方法
        Method method = methodSignature.getMethod();
        //拦截的方法的注解
        ArgsNotNull argsNotNull = method.getAnnotation(ArgsNotNull.class);
        //拦截的参数名称
        String[] parameters = methodSignature.getParameterNames();
        // 拦截的参数值
        Object[] args = joinPoint.getArgs();
        //注解的参数
        String[] needParams = argsNotNull.value();
        if (doCheckParams(needParams, parameters, args)) {
            return joinPoint.proceed();
        }
        return ServerResponse.createByWarningMsg("非法请求");
    }

    /**
     * 检查注解当中的参数
     *
     * @param needParams 注解中的参数,需要检查的参数
     * @param parameters 方法中传入的参数名称集合
     * @param args       方法中传入的参数集合
     */
    private Boolean doCheckParams(String[] needParams, String[] parameters, Object[] args) {
        for (String needParam : needParams) {
            if (needParam.contains(".") ? isWarpTypeNull(needParam, parameters, args) : isBasicTypeNull(needParam, parameters, args))
                return false;
        }
        return true;
    }

    /**
     * 检查基本类型参数
     * true 参数不为空,通过
     * false 参数为空,不通过
     *
     * @param param      需要检查的参数
     * @param parameters 方法的参数名称集合
     * @param args       方法的参数集合
     */
    private Boolean isBasicTypeNull(String param, String[] parameters, Object[] args) {
        int index = getParamIndex(param, parameters);
        return index >= 0 && args[index] == null;
    }

    /**
     * 检查非基本类型参数
     * true 参数不为空,通过
     * false 参数为空,不通过
     *
     * @param param      需要检查的参数
     * @param parameters 方法的参数名称集合
     * @param args       方法的参数集合
     */
    private Boolean isWarpTypeNull(String param, String[] parameters, Object[] args) {
        String[] split = param.split("\\.");
        int index = getParamIndex(split[0], parameters);
        if (index < 0)
            return true;
        //分解参数类型
        Field[] declaredFields = args[index].getClass().getDeclaredFields();
        try {
            for (Field field : declaredFields) {
                String fieldName = field.getName();//字段名称
                if (fieldName.equals(split[1])) {
                    field.setAccessible(true);//获取private成员变量
                    return field.get(args[index]) == null;
                }
            }
        } catch (IllegalAccessException e) {
            return true;
        }
        return false;
    }

    /**
     * 获取参数位置索引
     *
     * @param source     源参数
     * @param parameters 方法参数列表
     */
    private Integer getParamIndex(String source, String[] parameters) {
        for (int i = 0; i < parameters.length; i++) {
            if (source.equals(parameters[i]))
                return i;
        }
        return -1;
    }
}

搞定收工.

你可能感兴趣的:(Spring)