最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

手寫redis@Cacheable注解?參數(shù)java對(duì)象作為key值詳解

 更新時(shí)間:2022年01月03日 12:57:09   作者:不懂的浪漫  
這篇文章主要介紹了手寫redis@Cacheable注解?參數(shù)java對(duì)象作為key值詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

1.實(shí)現(xiàn)方式說明

本文在---- 手寫redis @ Cacheable注解支持過期時(shí)間設(shè)置   的基礎(chǔ)之上進(jìn)行擴(kuò)展。

1.1問題說明

@ Cacheable(key = “'leader'+#p0 +#p1 +#p2” )一般用法,#p0表示方法的第一個(gè)參數(shù),#p1表示第二個(gè)參數(shù),以此類推。

目前方法的第一個(gè)參數(shù)為Java的對(duì)象,但是原注解只支持Java的的基本數(shù)據(jù)類型。

1.2實(shí)現(xiàn)步驟

1.在原注解中加入新的參數(shù),

 objectIndexArray表示哪幾個(gè)角標(biāo)參數(shù)(從0開始)為java對(duì)象,objectFieldArray表示對(duì)應(yīng)位置該對(duì)象的字段值作為key

2.如何獲取參數(shù)的對(duì)象以及該字段的值

 使用的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整體流程沒有任何變化

主要是關(guān)鍵值獲取的方式,發(fā)生了變化

使用Java的反射技術(shù)

完整代碼如下:

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緩存處理 不適用與內(nèi)部方法調(diào)用(this.)或者private
 */
@Component
@Aspect
@Slf4j
public class NewCacheableAspect { 
    @Autowired
    private RedisUtil redisUtil;
 
    @Pointcut("@annotation(com.huajie.annotation.NewCacheable)")
    public void annotationPointcut() {
    }
 
    @Around("annotationPointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 獲得當(dāng)前訪問的class
        Class<?> className = joinPoint.getTarget().getClass();
        // 獲得訪問的方法名
        String methodName = joinPoint.getSignature().getName();
        // 得到方法的參數(shù)的類型
        Class<?>[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        Object[] args = joinPoint.getArgs();
        String key = "";
        int expireTime = 3600;
        try {
            // 得到訪問的方法對(duì)象
            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緩存注解參數(shù)異常", 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<String> 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中的參數(shù)名稱
    private static List<String> getKeyParsList(String key) {
        List<String> ListPar = new ArrayList<String>();
        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.測(cè)試

業(yè)務(wù)模塊使用方法controller

@RequestMapping("queryQuotaTreeData")
	@ResponseBody
	public List<TreeNode> getTreeData() {
		QuotaManage quotaManage = new QuotaManage();
		quotaManage.setQuotaName("測(cè)試22222");
		List<TreeNode> list  = this.quotaManageService.queryQuotaTreeData(quotaManage);
		return list;
	}
 

實(shí)現(xiàn)層objectIndexArray中的{0}表示第0個(gè)參數(shù),objectFieldArray中的“quotaName”表示對(duì)應(yīng)對(duì)象中的字段名稱

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

控制臺(tái)截圖拼接的get方法名稱和獲取的字段值

Redis的截圖

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java面向?qū)ο蠡A(chǔ)知識(shí)之?dāng)?shù)組和鏈表

    Java面向?qū)ο蠡A(chǔ)知識(shí)之?dāng)?shù)組和鏈表

    這篇文章主要介紹了Java面向?qū)ο蟮闹當(dāng)?shù)組和鏈表,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-11-11
  • 使用Springboot打成jar包thymeleaf的問題

    使用Springboot打成jar包thymeleaf的問題

    這篇文章主要介紹了使用Springboot打成jar包thymeleaf的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java中的日期時(shí)間類實(shí)例詳解(Date、Calendar、DateFormat)

    Java中的日期時(shí)間類實(shí)例詳解(Date、Calendar、DateFormat)

    在JDK1.0中,Date類是唯一的一個(gè)代表時(shí)間的類,但是由于Date類不便于實(shí)現(xiàn)國際化,所以從JDK1.1版本開始,推薦使用Calendar類進(jìn)行時(shí)間和日期處理,這篇文章主要介紹了Java中的日期時(shí)間類詳解(Date、Calendar、DateFormat),需要的朋友可以參考下
    2023-11-11
  • idea導(dǎo)入module全流程

    idea導(dǎo)入module全流程

    這篇文章主要介紹了idea導(dǎo)入module全流程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • java序列化與反序列化操作實(shí)例分析

    java序列化與反序列化操作實(shí)例分析

    這篇文章主要介紹了java序列化與反序列化操作,結(jié)合實(shí)例形式分析了java序列化與反序列化的概念與具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-10-10
  • MyBatis-Plus實(shí)現(xiàn)優(yōu)雅處理JSON字段映射

    MyBatis-Plus實(shí)現(xiàn)優(yōu)雅處理JSON字段映射

    默認(rèn)情況下,MyBatis-Plus 是不支持直接映射 JSON 類型的,這時(shí)候就需要借助其他的方法,下面小編就來和大家講講MyBatis-Plus如何優(yōu)雅處理JSON字段映射吧
    2025-04-04
  • SpringAop @Around執(zhí)行兩次的原因及解決

    SpringAop @Around執(zhí)行兩次的原因及解決

    這篇文章主要介紹了SpringAop @Around執(zhí)行兩次的原因及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java輸入/輸出流體系詳解

    Java輸入/輸出流體系詳解

    這篇文章主要介紹了Java輸入/輸出流體系詳解,涉及字節(jié)流和字符流,輸入輸出體系,轉(zhuǎn)換流,以及文件的讀寫等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • 微服務(wù)架構(gòu)設(shè)計(jì)RocketMQ進(jìn)階事務(wù)消息原理詳解

    微服務(wù)架構(gòu)設(shè)計(jì)RocketMQ進(jìn)階事務(wù)消息原理詳解

    這篇文章主要介紹了為大家介紹了微服務(wù)架構(gòu)中RocketMQ進(jìn)階層面事務(wù)消息的原理詳解,有需要的朋友可以借鑒參考下希望能夠有所幫助
    2021-10-10
  • springboot整合shiro登錄失敗次數(shù)限制功能的實(shí)現(xiàn)代碼

    springboot整合shiro登錄失敗次數(shù)限制功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了springboot整合shiro-登錄失敗次數(shù)限制功能,實(shí)現(xiàn)此功能如果是防止壞人多次嘗試,破解密碼的情況,所以要限制用戶登錄嘗試次數(shù),需要的朋友可以參考下
    2018-09-09

最新評(píng)論

渑池县| 资中县| 来宾市| 本溪市| 伊川县| 芦溪县| 双鸭山市| 东乡| 遂溪县| 旺苍县| 衡山县| 石城县| 磐石市| 若羌县| 务川| 贵州省| 舞钢市| 闵行区| 抚顺县| 昂仁县| 湟源县| 沾化县| 沙雅县| 元朗区| 泸西县| 怀宁县| 满洲里市| 蓬溪县| 广宗县| 涪陵区| 上饶县| 苏州市| 灵川县| 三原县| 永丰县| 弥勒县| 会宁县| 鄂托克旗| 临朐县| 无为县| 公安县|