自定义注解给查询加redis缓存

  • 背景
    接上篇(canal同步mysql数据到redis缓存:https://blog.csdn.net/Mr__simon/article/details/123549828)所讲,mysql同步redis通过canal实现,那接下来原有项目的查询加缓存应该有两种处理方式:1. 硬编码方式,重新封装查询方法,查询时先查缓存,缓存未查到查DB;2.使用自定义注解方式,需要使用的地方加自定义注解,使用aop切面统一进行处理。方式2较方式1代码侵入性低,且便于扩展。若是新开发,开发时就用方式1进行封装查询方法也可行,但是对于老项目改造,建议使用方式2,修改成本更低。

    现对自定义注解用切面方式进行说明。

  • 自定义注解RedisCache:

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RedisCache {
    
        /** redis key 前缀 */
        String keyPrefix();
    
        /** 类型 */
        Class clazz();
    }
    
  • 自定义注解使用:

    说明:该注解在service层或dao层都可使用,示例代码在dao层使用

    @Repository
    public interface AccountMapper {
    
        @RedisCache(keyPrefix = RedisCacheConstants.ACCOUNT_INFO_REDIS_KEY_PREFIX, clazz = AccountDO.class)
        AccountDO queryInfoByLoginName(String loginName);
    }
    
  • aop切面:

    /**
     * @Author: Simon
     * @Date: 2022-03-16 15:12
     * @Description: 查询走缓存:适合单表且全部查询走缓存
     */
    @Aspect
    @Component
    @Slf4j
    public class RedisCacheAspect {
    
        @Autowired
        private RedisUtil redisUtil;
    
        /**
         * 缓存切入点
         */
        @Pointcut("@annotation(com.dhzhly.core.order.common.annotation.RedisCache)")
        public void cachePointCut(){}
    
        @Around("cachePointCut() && @annotation(redisCache)")
        public Object around(ProceedingJoinPoint joinPoint, RedisCache redisCache) throws Throwable {
    
            String prefix = redisCache.keyPrefix();
            Class clazz = redisCache.clazz();
            Object[] args = joinPoint.getArgs();
            //这里只演示一个参数的情况,多个参数的可自行尝试
            if (clazz == null || args == null || args.length <= 0 || !(args[0] instanceof String)){
                Object result = joinPoint.proceed();
                return result;
            }
            String key = RedisCacheConstants.generateKey(prefix, (String) args[0]);
            String value = redisUtil.get(key);
            if (StringUtils.isNotBlank(value)){
                log.info("命中缓存");
                Object o = JSONUtil.toBean(value, clazz);
                return o;
            }
            log.info("未命中缓存");
            Object result = joinPoint.proceed();
            if (result != null){
                redisUtil.set(key, JSONUtil.toJsonStr(result), RedisCacheConstants.REFIS_KEY_TIMEOUT);
            }
            return result;
        }
    }
    
  • 工具类:

    /**
     * @author simon
     * @version 1.0.0
     * @Description
     * @createTime 2022/3/15
     */
    public class RedisCacheConstants {
    
        //缓存超时时间 7天
        public static final long REFIS_KEY_TIMEOUT = 60 * 60 * 24 * 7L;
    
        public static final String ACCOUNT_INFO_REDIS_KEY_PREFIX = "account_info::";
    
        public static String generateKey(String redisKey,String param) {
            return new StringBuffer().append(redisKey).append(param).toString();
        }
    }
    
    

若有多个服务都使用该功能,可以考虑将该功能封装成一个starter,需要 的服务直接依赖即可。
``

你可能感兴趣的:(java,缓存,redis,java)