SpringBoot 注解調用Redis緩存


注解代碼:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by qhong on 2018/9/5 11:12
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface CreditRedisCache {
	String prefix() default "huishi-server:credit";
}

利用攔截器處理注解中的方法,有就調用緩存,沒有就新增

import com.alibaba.fastjson.JSON;
import com.shitou.huishi.annotation.CreditRedisCache;
import com.shitou.huishi.utils.RedisUtil;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Collectors;
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;

/**
 * Created by qhong on 2018/9/5 11:13
 **/
@Aspect
@Component
@Slf4j
public class RedisCacheAspect {

	@Autowired
	RedisUtil redisUtil;

	/**
	 * 分隔符 生成key 格式為 類全類名|方法名|參數所屬類全類名
	 **/
	private static final String DELIMITER = "-";

	private static final Long expireTime=60*60*24*30L;

	/**
	 * Service層切點 使用到了我們定義的 RedisCache 作為切點表達式。
	 * 而且我們可以看出此表達式基於 annotation。
	 * 並且用於內建屬性為查詢的方法之上
	 */
	@Pointcut("@annotation(com.shitou.huishi.annotation.CreditRedisCache)")
	public void redisCacheAspect() {
	}

	/**
	 * Around 手動控制調用核心業務邏輯,以及調用前和調用后的處理,
	 * <p>
	 * 注意:當核心業務拋異常后,立即退出,轉向AfterAdvice 執行完AfterAdvice,再轉到ThrowingAdvice
	 *
	 * @param pjp the pjp
	 * @return object
	 * @throws Throwable the throwable
	 */
	@Around(value = "redisCacheAspect()")
	public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
		// 得到類名、方法名和參數
		String clazzName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] args = joinPoint.getArgs();

		// 根據類名、方法名和參數生成Key
		log.info("key參數: " + clazzName + "." + methodName);
		String key = getKey(clazzName, methodName, args);
		if (log.isInfoEnabled()) {
			log.info("生成key: " + key);
		}

		// 得到被代理的方法
		Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();

		//redis 前綴
		String prefix = method.getAnnotation(CreditRedisCache.class).prefix();

		// 檢查Redis中是否有緩存
		Object value =  redisUtil.get(prefix, key);

		// 得到被代理方法的返回值類型
		Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();

		// result是方法的最終返回結果
		Object result = null;
		try {
			if (null == value) {
				log.info("緩存未命中");
				// 調用數據庫查詢方法
				result = joinPoint.proceed(args);
				// 結果放入緩存
				redisUtil.set(prefix, key, result,expireTime);
			} else {
				// 緩存命中
				log.info("緩存命中, value = " + JSON.toJSONString(value));
				result = value;
			}
		} catch (Throwable e) {
			log.error("程序異常",e.getMessage());
			throw e;
		}
		return result;
	}

	/**
	 *      * 根據類名、方法名和參數生成Key
	 *      * @param clazzName
	 *      * @param methodName
	 *      * @param args
	 *      * @return key格式:全類名|方法名|參數類型
	 *
	 */
	private String getKey(String clazzName, String methodName, Object[] args) {
		StringBuilder key = new StringBuilder(clazzName);
		key.append(DELIMITER);
		key.append(methodName);
		key.append(DELIMITER);
		key.append(Arrays.stream(args).map(x->x.toString()).collect(Collectors.joining(DELIMITER)));
		return key.toString();
	}

}

使用:

	@CreditRedisCache
	public DataResponse queryICInfo(String name,String card)

直接在方法上使用即可,如果要自定義前綴,可以添加prefix,不然使用默認值。

這種很類似Spring-Cache,但是自己的代碼比較靈活 ,可以針對不同的模塊設定前綴,緩存時間等。

參考:

https://www.jianshu.com/p/95ddef3168f8

https://www.cnblogs.com/hongdada/p/9263699.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM