-
背景
接上篇(canal同步mysql数据到redis缓存:https://blog.youkuaiyun.com/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,需要 的服务直接依赖即可。
``