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 手动控制调用核心业务逻辑,以及调用前和调用后的处理,
     * 

* 注意:当核心业务抛异常后,立即退出,转向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

你可能感兴趣的:(SpringBoot 注解调用Redis缓存)