AOP技术限制后端接口调用次数

AOP技术限制后端接口调用次数,第1张

AOP技术限制后端接口调用次数

AOP技术限制后端接口调用次数
  • 背景
  • 一、整体方案
  • 二、AOP
    • 1.反射解析属性
    • 2.SpEL解析属性
    • 3.下载接口
    • 4.预览接口
  • 总结


背景

最近工作上在做安全管控的需求,需要限制一些接口的调用次数,一般可以采用两种方案,一种是将在后端使用AOP进行限制,另外一种是在后端开一个http接口,前端每次调用的时候,先调用安全管控的接口,接口返回成功的情况下,才进行实际业务 *** 作。本文主要总结使用AOP限制次数踩的一些坑


一、整体方案


整体方案如上图所示,使用AOP技术,在原有的基础上,增加规则判断。

二、AOP 1.反射解析属性

getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
同样类似的还有getConstructors()和getDeclaredConstructors()、getMethods()和getDeclaredMethods(),这两者分别表示获取某个类的方法、构造函数。

private Object parseFieldValue(JoinPoint jp, String filed){
        Signature signature = jp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        Object[] args = jp.getArgs();
        String[] parameterNames = methodSignature.getParameterNames();
        Class[] parameterTypes = method.getParameterTypes();
        String[] filedNames = filed.split("\.");
        for (int i = 0; i < parameterNames.length; i++){
            if (!parameterNames[i].equals(filedNames[0])){
                continue;
            }

            if (filedNames.length == 1){
                return args[i];
            }

            try{
                return parseFiled(parameterTypes[i], args[i], filedNames, 1);
            } catch (IllegalAccessException e1){
                e1.printStackTrace();
            }
        }

        throw new IllegalArgumentException("解析field失败");
    }

    private Object parseFiled(Class parameterType, Object targetObject, String[] filedNames, int index) throws IllegalAccessException{
        try{
            Field field = parameterType.getDeclaredField(filedNames[index]);
            field.setAccessible(true);
            Object result = field.get(targetObject);
            if (filedNames.length == index){
                return result;
            } else {
                return parseFiled(result.getClass(), result, filedNames, ++index);
            }
        } catch (NoSuchFieldException e) {
            return parseFiled(parameterType.getSuperclass(), targetObject, filedNames, index);
        }
    }
2.SpEL解析属性
private  T parseSpel(ProceedingJoinPoint jp, String spel, Class clazz, T defaultResult) {
        expressionParser parser = new SpelexpressionParser();
        Signature signature = jp.getSignature();
        MethodSignature methodSignature = null;
        if (signature instanceof MethodSignature){
            methodSignature = (MethodSignature) signature;
        }
        if (methodSignature == null){
            return defaultResult;
        }

        Method method = methodSignature.getMethod();
        String[] params = methodSignature.getParameterNames();
        Object[] arguments = jp.getArgs();
        evaluationContext context = new StandardevaluationContext();
        for (int len = 0; len < params.length; len++) {
            context.setVariable(params[len], arguments[len]);
        }
        try {
            expression expression = parser.parseexpression(spel);
            return expression.getValue(context, clazz);
        } catch (Exception e) {
            return defaultResult;
        }
    }
3.下载接口

附件下载的时候,由于下载直接是浏览器控制,所以返回特定的错误,或者返回null,对于用户的提示效果都不太好。可以通过页面跳转到固定的错误页面,或者直接html的方式进行解决。

4.预览接口

项目上面预览使用的viewer.js来做的,直接url绑定到img上面,所以这个根本上就没有好的方法给用户进行提示,只能在前端进行改造。

总结

涉及前端到类似的方案评审的时候,需要拉上前端的同事,自己本来是前端小白,经验有限,临时改方案,增加自己的工作量,吃力不讨好。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5691577.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存