使用aop对传参Map进行参数拦截校验

个人使用工具记录(后续使用在修改)

controller 接收参数通常是 Map,里面有很多的简单的非空、类型、正则校验。避免写大量的重复代码。在网上搜索和自己总结

使用效果图

参考AOP参数校验_aop实现参数校验_开心比较堵的博客-CSDN博客

@PostMapping("/test")
@NotTokenMethod
public Object test(@RequestBody Map<String, Object> map) {
    System.out.println(map);
    return map;
}

根据一个总体的注解

@MapParIntercept

里面放多个注解  @MapParam 来进行配置校验

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MapParIntercept {
    MapParam[] value();
}
/**
 * 参数校验具体实现
 *
 * @Author cj
 * @Date 2023/11/23 10:03
 * @Version 1.0
 */
public @interface MapParam {
    /**
     * 校验提示
     *
     * @return
     */
    String message() default "";

    /**
     * 要校验的key
     *
     * @return
     */
    String key();

    ParTypeEnum verifyType();

    /**
     * 正则
     *
     * @return
     */
    String regex() default "";

}

MapParam中的主要是使用 ParTypeEnum 枚举进行一个功能添加和代码逻辑运行



import java.util.List;

/**
 * @Author cj
 * @Date 2023/11/23 10:59
 * @Version 1.0
 */

public enum ParTypeEnum {


    /**
     * 正则校验
     */
    regex(200, VerifyCommValueInterface.regex, VerifyCommValueInterface.check_regex_error),
    /**
     * 判断参数类型必须是 整数
     */
    isInt(103, VerifyCommValueInterface.isInt, VerifyCommValueInterface.check_is_int
            , true, Integer.class,int.class),
    /**
     * 判断参数类型必须是 数字
     */
    isNumber(102, VerifyCommValueInterface.isNumber, VerifyCommValueInterface.check_is_number),
    /**
     * 判断参数类型必须是 字符串
     */
    isString(101, VerifyCommValueInterface.isString, VerifyCommValueInterface.check_is_string
            , true, String.class),
    /**
     * 判断参数类型必须是 数组
     */
    isArray(100, VerifyCommValueInterface.isArray, VerifyCommValueInterface.check_is_array
            , true, List.class),
    /**
     * 非空校验,也就必填校验
     */
    notBlank(0, VerifyCommValueInterface.notBlank, VerifyCommValueInterface.check_is_blank);


    private int code;

    private String type;

    private String message;

    private Class[] aClass;

    private boolean isType = false;


    public String getMessage() {
        return this.message;
    }

    public String getType() {
        return this.type;
    }

    public boolean isType() {
        return isType;
    }

    public int getCode() {
        return this.code;
    }

    public Class[] getaClass() {
        return this.aClass;
    }

    ParTypeEnum(int code, String type) {
        this.code = code;
        this.type = type;
    }

    ParTypeEnum(int code, String type, String message) {
        this.code = code;
        this.type = type;
        this.message = message;
    }

    ParTypeEnum(int code, String type, String message, boolean isType, Class... aClass) {
        this.code = code;
        this.isType = isType;
        this.type = type;
        this.message = message;
        this.aClass = aClass;
    }

}

将一些测量值存储使用 VerifyCommValueInterface



/**
 * @Author cj
 * @Date 2023/11/23 10:25
 * @Version 1.0
 */
public interface VerifyCommValueInterface {
    String success = "操作成功";

    String error = "操作失败";
    String select_error = "查询异常";
    String check_error = "查询异常";
    String par_is_null = "参数为空";
    String check_is_blank = "参数不能为空";
    String check_is_array = "参数类型错误,需要数组";
    String check_is_string = "参数类型错误,需要字符串";
    String check_is_number = "参数类型错误,需要数字";
    String check_is_int = "参数类型错误,需要整数";
    String check_regex_error = "参数格式不匹配";
    String operation_error = "请联系开发人员";


    /**
     * 用于类型判断 是否是整数
     */
    String isInt = "isInt";
    /**
     * 用于类型判断 是否是数字
     */
    String isNumber = "isNumber";
    /**
     * 用于类型判断 是否是字符串
     */
    String isString = "isString";
    /**
     * 用于类型判断 是否是数组
     */
    String isArray = "isArray";
    /**
     * 用于值判断 是否是为空
     */
    String notBlank = "notBlank";
    /**
     * 用于值判断 是否是为空
     */
    String regex = "regex";


}

最后使用aop的前置 进行拦截 

MapParAspect
/**
 * @Author cj
 * @Date 2023/11/23 11:34
 * @Version 1.0
 */

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author cj * @date 2023年11月23日 11:34
 */

@Aspect
@Component
public class MapParAspect {
    private static final Logger logger = LoggerFactory.getLogger(MapParAspect.class);

    @Pointcut("@annotation(com.sckj.hydsj.annotation.MapParIntercept)")
    private void MapParIntercept() {

    }

    @Before("MapParIntercept()")
    public void interceptorDo(JoinPoint point) throws Exception {
//        try {
        logger.info("参数校验");
        //获取目标对象
        Object target = point.getTarget();
        //获取方法参数
        Object[] argements = point.getArgs();
        //获取方法名
        String methodName = point.getSignature().getName();
        //获取参数类型
        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();
        //反射获取该方法
        Method method = target.getClass().getMethod(methodName, parameterTypes);
        MapParIntercept interceptor = method.getAnnotation(MapParIntercept.class);
        if (interceptor == null) {
            return;
        } else {
            MapParam[] value = interceptor.value();
            if (argements.length != 0) {
                Object argement = argements[0];
                if (argement instanceof Map) {
                    Map<String, Object> reqMap = (Map<String, Object>) argement;
                    for (MapParam mapParam : value) {
                        String key = mapParam.key();
                        ParTypeEnum parTypeEnum = mapParam.verifyType();
                        String message = mapParam.message();
                        String type = parTypeEnum.getType();
                        if (StringUtils.isEmpty(message)) {
                            message = parTypeEnum.getMessage();
                        }
                        message = key + ":" + message;
                        //是否根据类型判断
                        boolean isTypeBoolean = parTypeEnum.isType();
                        //判断前端传参没
                        if (!reqMap.containsKey(key)) {
                            throw new RuntimeException(key + ":" + VerifyCommValueInterface.par_is_null);
                        }
                        Object parValue = reqMap.get(key);
                        if (isTypeBoolean) {
                            //获取数据类型
                            Class[] classes = parTypeEnum.getaClass();
                            boolean isTrue = false;
                            for (Class aClass : classes) {
                                if (aClass.isInstance(parValue)) {
                                    isTrue = true;
                                    break;
                                }
                            }
                            if (!isTrue) {
                                throw new RuntimeException(message);
                            }
                        }
                        if (VerifyCommValueInterface.notBlank.equals(type)) {
                            //判断是否为空
                            if (StringUtils.isEmpty(parValue)) {
                                throw new RuntimeException(message);
                            }
                        } else if (VerifyCommValueInterface.regex.equals(type)) {
                            //获取正则规则
                            String regexPattern = mapParam.regex();
                            //正则校验
                            Pattern pattern = Pattern.compile(regexPattern);
                            // 进行匹配
                            boolean matches = pattern.matcher(String.valueOf(parValue)).matches();
                            if (!matches) {
                                throw new RuntimeException(message);
                            }
                        }

                    }
                }
            }

        }
        /**
         * 参数校验
         */
//        } catch (Exception e) {
//            logger.error("参数校验失败", e);
//            throw new RuntimeException(e);
//        }
        logger.info("校验成功");
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值