双拦截链+aop实现智能参数检查

news/2024/7/24 12:32:17 标签: 拦截链, aop, 设计模式, 参数检查, java

文章目录

aop_1">双拦截链+aop实现智能参数检查

注解类

java">@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER,ElementType.FIELD})
@Documented
public @interface CheckEmail {
    String msg() default "email format invalid";
}

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NotEmpty {

  String msg() default "字段不能为空";
  
}

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NotNull {

  String msg() default "字段不能为NULL";
  
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER,ElementType.FIELD})
@Documented
public @interface CheckUser {
    String msg() default "current user dose not exist";
}


/**
 * 标注在参数bean上,表示需要对该参数校验
 */
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidParam {
  
  
}

aspect

java">@Component
@Aspect
public class FieldVerify {


    private List<Handler> paramChainHandler = new ArrayList<>();
    {
        paramChainHandler.add(new NotNullHandler());//null
        paramChainHandler.add(new NotEmptyHandler());//空值,“null”,“undefined”
        paramChainHandler.add(new CheckEmailHandler());//邮箱格式
        paramChainHandler.add(new CheckUserHandler());//用户是否存在检查
        paramChainHandler.add(new ReleaseHandler());//释放的handler,以后要再加节点应该加在此节点前
        paramChainHandler.add(new ValidParamHandler());//处理@ValidParam
    }


    @Before("execution(* com.ruoyi.project.app.controller.box.*.*(..))")
    public void fieldVerify(JoinPoint point) throws Exception {
        //获取参数对象
        Object[] args = point.getArgs();
        //获取方法参数
        MethodSignature signature = (MethodSignature) point.getSignature();
        Parameter[] parameters = signature.getMethod().getParameters();

        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            for(Handler handler:paramChainHandler){
                if(handler instanceof ValidParamHandler){
                    handler.handler(parameter,args);
                }else{
                    if(handler.handler(parameter,args[i])){
                        //ReleaseHandler释放掉整条链
                        break;
                    }
                }
            }
        }
    }

}

handler

java">public interface Handler {
    /**
     * 处理器接口
     * 拦截链某节点处理成功,说明参数不符合要求,则会抛出异常
     * 如果返回false说明参数正常,应交由下一个节点处理
     * 如果返回true(只有这个ReleaseHandler会返回true),应该释放掉整条链的执行
     * @param element 参数Parameter对象或者Field属性
     * @param obj 参数对象
     * @return
     */
    boolean handler(AnnotatedElement element, Object obj) throws IllegalAccessException;

}
java">public class CheckEmailHandler implements Handler{

    @Override
    public boolean handler(AnnotatedElement element, Object obj) {
        Class<?> clazzType = null;
        CheckEmail checkEmail = null;
        if(element instanceof Parameter){
            Parameter  parameter = (Parameter) element;
            clazzType = parameter.getType();
            checkEmail = parameter.getAnnotation(CheckEmail.class);
        }else if(element instanceof Field){
            Field field = (Field) element;
            clazzType = field.getType();
            checkEmail = field.getAnnotation(CheckEmail.class);
        }
        if(clazzType==String.class&&checkEmail != null&&!RegexValidate.validationEmail((String)obj)){
            throw new RuntimeException(checkEmail.msg());
        }
        return false;
    }
}

java">public class CheckUserHandler implements Handler {
    @Override
    public boolean handler(AnnotatedElement element, Object obj) {
        CheckUser checkUser = null;
        if(element instanceof Parameter){
            Parameter  parameter = (Parameter) element;
            checkUser = parameter.getAnnotation(CheckUser.class);
        }else if(element instanceof Field){
            Field field = (Field) element;
            checkUser = field.getAnnotation(CheckUser.class);
        }
        if(checkUser!=null){
            if(null==SpringUtils.getBean(IAppUserService.class).selectAppUserById((Long)obj)){
                throw new RuntimeException(checkUser.msg());
            }
        }
        return false;
    }
}
java">public class NotEmptyHandler implements Handler{
    @Override
    public boolean handler(AnnotatedElement element,Object obj) {
        Class<?> clazzType = null;
        NotEmpty notEmpty = null;
        if(element instanceof Parameter){
            Parameter  parameter = (Parameter) element;
            clazzType = parameter.getType();
            notEmpty = parameter.getAnnotation(NotEmpty.class);
        }else if(element instanceof Field){
            Field field = (Field) element;
            clazzType = field.getType();
            notEmpty = field.getAnnotation(NotEmpty.class);
        }

        if(clazzType==String.class&&notEmpty != null&&StringUtils.isInvalid((String) obj)){
            throw new RuntimeException(notEmpty.msg());
        }
        return false;
    }
}
java">public class NotNullHandler implements Handler{
    @Override
    public boolean handler(AnnotatedElement element, Object obj) {
        NotNull notNull = null;
        if(element instanceof Parameter){
            Parameter  parameter = (Parameter) element;
            notNull = parameter.getAnnotation(NotNull.class);
        }else if(element instanceof Field){
            Field field = (Field) element;
            notNull = field.getAnnotation(NotNull.class);
        }

        if (notNull != null && obj == null) {
            throw new RuntimeException(notNull.msg());
        }
        return false;
    }
}
java">public class ReleaseHandler implements Handler {
    @Override
    public boolean handler(AnnotatedElement element, Object obj) {
        Class<?> clazzType = null;
        ValidParam validParam = null;
        if(element instanceof Parameter){
            Parameter  parameter = (Parameter) element;
            clazzType = parameter.getType();
            validParam = parameter.getAnnotation(ValidParam.class);
        }else if(element instanceof Field){
            Field field = (Field) element;
            clazzType = field.getType();
            validParam = field.getAnnotation(ValidParam.class);
        }

        if (clazzType.isAssignableFrom(HttpServletRequest.class) || clazzType.isAssignableFrom(HttpSession.class) ||
                clazzType.isAssignableFrom(HttpServletResponse.class) || validParam == null) {
            //逻辑到这里就是参数已经没必要再检查了,因为满足上述条件之一就没必要在检查参数,应该释放整条链
            return true;
        }
        return false;
    }
}
java">public class ValidParamHandler implements Handler {

    private List<Handler> validParamChainHandler = new ArrayList<>();
    {
        validParamChainHandler.add(new NotNullHandler());//null
        validParamChainHandler.add(new NotEmptyHandler());//空值,“null”,“undefined”
        validParamChainHandler.add(new CheckEmailHandler());//邮箱格式
        validParamChainHandler.add(new CheckUserHandler());//用户是否存在检查
    }

    @Override
    public boolean handler(AnnotatedElement element, Object obj) throws IllegalAccessException {
        //到这里一定是参数标注了ValidParam注解

        Class<?> paramClazz = null;
        if(element instanceof Parameter){
            Parameter  parameter = (Parameter) element;
            paramClazz = parameter.getType();
        }else if(element instanceof Field){
            Field field = (Field) element;
            paramClazz = field.getType();
        }

        //获取类型所对应的参数对象,实际项目中Controller中的接口不会传两个相同的自定义类型的参数,所以此处直接使用findFirst()
        Class<?> finalParamClazz = paramClazz;
        Object arg = Arrays.stream((Object[])obj).filter(ar -> finalParamClazz.isAssignableFrom(ar.getClass())).findFirst().get();
        //得到参数的所有成员变量
        Field[] declaredFields = paramClazz.getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            //二次责任链
            for(Handler handler:validParamChainHandler){
                handler.handler(field,field.get(arg));
            }
        }
        return false;
    }
}

用法

单一参数

java">public Result sendEmailCode(@NotEmpty @CheckEmail @PathVariable @ApiParam("邮件地址") String email)

bean参数

java"> public Result register(@RequestBody @ValidParam AccountVo account){}

@ApiModel("账户实体")
public class AccountVo implements Serializable {

    @ApiModelProperty("邮箱")
    @CheckEmail
    @NotEmpty
    private String email;

    @NotEmpty
    @ApiModelProperty("密码")
    private String password;
}

http://www.niftyadmin.cn/n/1037460.html

相关文章

字节排序函数

文章目录字节排序函数大小端字节序字节序转换字节排序函数 大小端字节序 大端模式&#xff1a;高序字节存储在低地址 小端模式&#xff1a;低序字节存储在低地址 主机字节序基于不同操作系统而不同&#xff0c;有些系统采用大端&#xff0c;有些则使用小端 网络字节序都是采…

netty源码之EventLoopGroup

文章目录netty源码之EventLoopGroup前言类图及接口说明源码分析默认选择策略工厂事件执行器选择工厂newChildopenSelector总结netty源码之EventLoopGroup 前言 本文基于windows下的netty4.1.41.Final版本&#xff0c;以后也都是基于此版本, 注意&#xff0c;不太相关的代码笔…

css改变placeholder颜色

基本写法 input::-webkit-input-placeholder {color: #ff4949; }如果你用到vue项目 样式设置了scoped 你就用 input>>>::-webkit-input-placeholder {color: #ff4949; }不得不承认 在有些需求上 这东西还是挺有用的

netty源码之channel初始化

文章目录netty源码之channel初始化入口说明channel初始化netty源码之channel初始化 入口说明 ChannelFuture future server.bind(port).sync();AbstractBootstrap#bind(int inetPort)AbstractBootstrap#bind(SocketAddress localAddress)AbstractBootstrap#doBind(final Soc…

JavaScript验证邮箱格式是否正确

//验证邮箱 function checkEmail(value) {return /^[A-Za-z\d]([-_.][A-Za-z\d])*([A-Za-z\d][-.])[A-Za-z\d]{2,4}$/.test(value) }

电脑如何关闭防火墙

正常情况下我们都会为了安全开着防火墙 但也有时我们开发为了让同事能访问我们电脑的都想就会不得已要关闭防火墙 那么关闭防火墙 步骤 一起来看看吧 找到 此电脑/此计算机 右键选择 属性 或者直接打开设置也可以 搜索控制面板 在控制面板中找到并打开 Windows Defender防火墙…

谷歌查看请求选择只看接口

打开F12 调试工具 选择Network 这是我们会发现 什么图片 文件 接口的请求乱七八糟的 正常情况我们需要的都是只看接口 先点击这里这个 过滤 我们只需要点击 Fetch/XHR 即可过滤掉其他请求信息的展示

TypeScript 入门 搭建环境 构建自己的第一个TypeScript 案例

打开项目目录 在终端输入 npm i typescript -g然后创建一个ts文件 我这里叫 index.ts 和我同名可以解决很多问题哦 然后 我们在index.ts中输入代码如下 function DomConst(){let Dom: String 我的第一个TS案例;console.log(Dom); } DomConst();然后在终端输入 tsc index.ts…