zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    colorDialog颜色拾取
    ContextMenuStrip菜单
    C#根据当前时间确定日期范围(本周、本月、本季度、本年度及常见日期方法荟萃
    重设切片上下文
    DomainUpDown 控件
    SQL中使用WITH AS提高性能
    在Reporting Service中使用下拉框提供参数查询
    c# 发射机制
    Silverlight 浏览器外运行及更新判断
    自动化持续集成编译 配置 CruiseControl.Net SVN
  • 原文地址:https://www.cnblogs.com/hongdada/p/9592725.html
Copyright © 2011-2022 走看看