千家信息网

java对象作为key值的实例分析

发表于:2024-11-25 作者:千家信息网编辑
千家信息网最后更新 2024年11月25日,这篇文章给大家介绍java对象作为key值的实例分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1.实现方式说明下面在---- 手写redis @ Cacheable注解支持过
千家信息网最后更新 2024年11月25日java对象作为key值的实例分析

这篇文章给大家介绍java对象作为key值的实例分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。


    1.实现方式说明

    下面在---- 手写redis @ Cacheable注解支持过期时间设置 的基础之上进行扩展。

    1.1问题说明

    @ Cacheable(key = "'leader'+#p0 +#p1 +#p2" )一般用法,#p0表示方法的第一个参数,#p1表示第二个参数,以此类推。

    目前方法的第一个参数为Java的对象,但是原注解只支持Java的的基本数据类型。

    1.2实现步骤

    1.在原注解中加入新的参数,

    objectIndexArray表示哪几个角标参数(从0开始)为java对象,objectFieldArray表示对应位置该对象的字段值作为key

    2.如何获取参数的对象以及该字段的值

    使用的java的反射,拼接get方法获取该字段值。

    2.源代码

    修改java注解@ExtCacheable,本文中使用@NewCacheable

    package com.huajie.annotation; import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; @Target({ ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface NewCacheable {         String key() default "";               int[] objectIndexArray();         String[] objectFieldArray();         int expireTime() default 1800;//30分钟     }

    SpringAop切面NewCacheableAspect

    获取AOP整体流程没有任何变化

    主要是关键值获取的方式,发生了变化

    使用Java的反射技术

    完整代码如下:

    package com.huajie.aspect; import com.huajie.annotation.NewCacheable;import com.huajie.utils.RedisUtil;import com.huajie.utils.StringUtil;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List; /** * redis缓存处理 不适用与内部方法调用(this.)或者private */@Component@Aspect@Slf4jpublic class NewCacheableAspect {     @Autowired    private RedisUtil redisUtil;     @Pointcut("@annotation(com.huajie.annotation.NewCacheable)")    public void annotationPointcut() {    }     @Around("annotationPointcut()")    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {        // 获得当前访问的class        Class className = joinPoint.getTarget().getClass();        // 获得访问的方法名        String methodName = joinPoint.getSignature().getName();        // 得到方法的参数的类型        Class[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();        Object[] args = joinPoint.getArgs();        String key = "";        int expireTime = 3600;        try {            // 得到访问的方法对象            Method method = className.getMethod(methodName, argClass);            method.setAccessible(true);            // 判断是否存在@ExtCacheable注解            if (method.isAnnotationPresent(NewCacheable.class)) {                NewCacheable annotation = method.getAnnotation(NewCacheable.class);                key = getRedisKey(args, annotation);                expireTime = getExpireTime(annotation);            }        } catch (Exception e) {            throw new RuntimeException("redis缓存注解参数异常", e);        }        log.info(key);        boolean hasKey = redisUtil.hasKey(key);        if (hasKey) {            return redisUtil.get(key);        } else {            Object res = joinPoint.proceed();            redisUtil.set(key, res);            redisUtil.expire(key, expireTime);            return res;        }    }     private int getExpireTime(NewCacheable annotation) {        return annotation.expireTime();    }     private String getRedisKey(Object[] args, NewCacheable annotation) throws Exception{        String primalKey = annotation.key();        // 获取#p0...集合        List keyList = getKeyParsList(primalKey);        for (String keyName : keyList) {            int keyIndex = Integer.parseInt(keyName.toLowerCase().replace("#p", ""));            Object parValue = getParValue(annotation, keyIndex, args);            primalKey = primalKey.replace(keyName, String.valueOf(parValue));        }        return primalKey.replace("+", "").replace("'", "");    }     private Object getParValue(NewCacheable annotation, int keyIndex, Object[] args) throws Exception{        int[] objectIndexArray = annotation.objectIndexArray();        String[] objectFieldArray = annotation.objectFieldArray();        if (existsObject(keyIndex, objectIndexArray)) {            return getParValueByObject(args, keyIndex, objectFieldArray);        } else {            return args[keyIndex];        }    }     private Object getParValueByObject(Object[] args, int keyIndex, String[] objectFieldArray) throws Exception {        Class cls = args[keyIndex].getClass();        Method method;        if(objectFieldArray!=null&&objectFieldArray.length>=keyIndex){             method = cls.getMethod("get" + StringUtil.firstCharToUpperCase(objectFieldArray[keyIndex]));        }else{             method = cls.getMethod("get" + StringUtil.firstCharToUpperCase(cls.getFields()[0].getName()));        }        method.setAccessible(true);        log.info(method.getName());        return method.invoke(args[keyIndex]);    }     private boolean existsObject(int keyIndex, int[] objectIndexArray) {        if (objectIndexArray == null || objectIndexArray.length <= 0) {            return false;        }        for (int i = 0; i < objectIndexArray.length; i++) {            if (keyIndex == objectIndexArray[i]) {                return true;            }        }        return false;    }     // 获取key中#p0中的参数名称    private static List getKeyParsList(String key) {        List ListPar = new ArrayList();        if (key.indexOf("#") >= 0) {            int plusIndex = key.substring(key.indexOf("#")).indexOf("+");            int indexNext = 0;            String parName = "";            int indexPre = key.indexOf("#");            if (plusIndex > 0) {                indexNext = key.indexOf("#") + key.substring(key.indexOf("#")).indexOf("+");                parName = key.substring(indexPre, indexNext);            } else {                parName = key.substring(indexPre);            }            ListPar.add(parName.trim());            key = key.substring(indexNext + 1);            if (key.indexOf("#") >= 0) {                ListPar.addAll(getKeyParsList(key));            }        }        return ListPar;    } }

    3.测试

    业务模块使用方法controller

    @RequestMapping("queryQuotaTreeData")        @ResponseBody        public List getTreeData() {                QuotaManage quotaManage = new QuotaManage();                quotaManage.setQuotaName("测试22222");                List list  = this.quotaManageService.queryQuotaTreeData(quotaManage);                return list;        }
     

    实现层objectIndexArray中的{0}表示第0个参数,objectFieldArray中的"quotaName"表示对应对象中的字段名称

    @Override        @NewCacheable(key="test+#p0",objectIndexArray = {0},objectFieldArray = {"quotaName"})        public List queryQuotaTreeData(QuotaManage quotaManage) {                List returnNodesList = new ArrayList();                List nodeList = this.mapper.queryQuotaTreeData();                returnNodesList = treeUtils.getParentList(nodeList);                log.info(nodeList.size()+"");                return returnNodesList;                        }
     

    控制台截图拼接的get方法名称和获取的字段值

    Redis的截图

    关于java对象作为key值的实例分析就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

    参数 方法 对象 注解 字段 名称 实例 实例分析 分析 内容 截图 方式 更多 类型 缓存 反射 变化 帮助 支持 测试 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 怎么在服务器管理器中添加功能 网络安全教育图片 图片素材 软件开发项目启动资金预算 服务器一般能用几年 数据库字段 类型 规则 广东数据库安全审计 我的世界服务器怎么开挂 软件工程是研究软件开发 长春质量网络技术咨询有哪些 怎么在服务器中查看数据库 服务器机柜托架 如何使用服务器上的sql 数据库关系范式有几种 李玉婷数据库试题视频 软件开发专业没学好能干嘛 2020网络安全事件分析 服务器安全狗添加端口 区块链技术怎么用到云数据库 浙江软件开发代理价钱 网络技术工程师 教程 服务器下电长按开机键 高青薪酬管理hr软件开发公司 一直做pc端软件开发的出路 共享服务器文件怎么恢复 数据库系统应用与开发 考试 mysql数据库的搭建 输入法软件开发论文 如何搭建域名服务器 服务器硬盘有坏道怎么恢复 服务器与电脑直连怎么打开web
    0