1. 建立Cacheable注解类
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Cacheable { String value() default ""; String key() default ""; int expire() default 3600; }
2. Aspect拦截并缓存结果,也可以直接用SpringBoot RedisTemplate
@Component public class RedisClient { private static final Logger logger = LoggerFactory.getLogger(RedisClient.class); @Value("${spring.redis.host}") public String host; @Value("${spring.redis.port}") public int port; @Value("${spring.redis.password}") public String password; public JedisPool jedisPool; public RedisClient(){ } public RedisClient(JedisPool pool) { this.jedisPool = pool; } @Bean public RedisClient getDefaultClient(){ JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(100); config.setMaxTotal(1000); this.jedisPool = new JedisPool(config, host, port, 6000, password); RedisClient client = new RedisClient(this.jedisPool); return client; } public Long setnx(String key, String value) { Jedis client = jedisPool.getResource(); try { Long result = client.setnx(key, value); return result; } finally { client.close(); } } public String getSet(String key, String newValue) { Jedis client = jedisPool.getResource(); try { return client.getSet(key, newValue); } finally { client.close();// 向连接池“归还”资源 } } public boolean set(String key, String value) { Jedis client = jedisPool.getResource(); String isSuccess ; try { isSuccess = client.set(key, value); if ("OK".equals(isSuccess)) { return true; } else { return false; } } finally { client.close();// 向连接池“归还”资源 } } /** * 根据key来获取对应的value */ public Object getKey(String key) { Jedis client = jedisPool.getResource(); Object o = null; try { o = client.get(key); } finally { client.close();// 向连接池“归还”资源 } return o; } /** * * @param key * @param seconds * @return */ public Long expire(String key,Integer seconds){ Jedis client = jedisPool.getResource(); Long success = 1l; try{ success = client.expire(key, seconds); }finally{ client.close(); } return success; } public boolean delKey(String key) { Jedis client = jedisPool.getResource(); try { client.del(key); logger.info("del key:{}, result:{}",key, client.get(key)); return true; } finally { client.close(); } } /**set Object*/ public String setSerialize(String key,Object object) { Jedis client = jedisPool.getResource(); logger.info("setSerialize key:{},value:{}",key, new Gson().toJson(object)); logger.info("SerializeUtil.serialize(object): " + SerializeUtil.serialize(object)); try { return client.set(key.getBytes(), SerializeUtil.serialize(object)); } finally { client.close(); } } /**get Object*/ public Object getSerialize(String key) { Jedis client = jedisPool.getResource(); byte[] value; try { value = client.get(key.getBytes()); } finally { client.close(); } if(value == null){ return value; } logger.info("getSerialize key:{},value:{}",key,new Gson().toJson(SerializeUtil. unserialize(value))); return SerializeUtil. unserialize(value); } /**delete a key**/ public boolean delSerialize(String key) { Jedis client = jedisPool.getResource(); try { return client.del(key.getBytes())>0; } finally { client.close(); } } }
@Slf4j @Aspect @Component public class CacheLockAspect { @Autowired private RedisClient redisClient; /* @Around("@annotation(annotation.CacheLock)") public Object cacheable(ProceedingJoinPoint pjp) throws Throwable { Method method = this.getMethod(pjp); CacheLock cacheLock = method.getAnnotation(CacheLock.class); if (cacheLock == null) { log.info("no CacheLock annotation"); return pjp.proceed(); } String key = getCacheKey(cacheLock.key(), cacheLock.value(), method, pjp.getArgs()); boolean result = lock.lock(key, cacheLock.expireTime()); if (!result) {// 锁失败,证明被其他线程持有 log.info("get lock fail"; return null; } try { // 执行方法 return pjp.proceed(); } finally { lock.unlock(key);// 释放锁 } }*/
@Around("@annotation(Cacheable对应包名)") public Object getCacheable(ProceedingJoinPoint pjp) throws RuntimeException { Object obj = null; Method method = this.getMethod(pjp); Cacheable cacheable = method.getAnnotation(Cacheable.class); int expire = cacheable.expire(); String key = this.getCacheKey(cacheable.key(), cacheable.value(), method, pjp.getArgs()); try { obj = redisClient.getSerialize(key); } catch (Exception var12) { log.warn("redis connection exception : {}", var12); } if(obj != null) { log.debug("before method:{} cacheable get cache key:{} data:{}", new Object[]{method.getName(), key, obj}); return obj; } else { try { obj = pjp.proceed(); } catch (Throwable var11) { log.warn("redis cacheable aspect proceed exception:{}", var11); throw new RuntimeException(var11); } if(obj != null) { try { redisClient.setSerialize(key,obj); redisClient.expire(key,expire); } catch (Exception var10) { log.warn("redis connection exception : {}", var10); } log.debug("after method:{} cacheable set cache key:{} data:{}", new Object[]{method.getName(), key, obj}); } return obj; } } @SuppressWarnings("rawtypes") private Method getMethod(ProceedingJoinPoint pjp) { Object[] args = pjp.getArgs(); Class[] argTypes = new Class[pjp.getArgs().length]; for (int method = 0; method < args.length; ++method) { argTypes[method] = args[method].getClass(); } Method var8 = null; try { var8 = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(), argTypes); return var8; } catch (NoSuchMethodException var6) { log.warn("redis cacheable aspect no such method exception:{}", var6); throw new RuntimeException(var6); } catch (SecurityException var7) { log.warn("redis cacheable aspect method security exception:{}", var7); throw new RuntimeException(var7); } } private String getCacheKey(String key, String value, Method method, Object[] args) { LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer(); String[] paraNameArr = u.getParameterNames(method); SpelExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); for (int i = 0; i < paraNameArr.length; ++i) { context.setVariable(paraNameArr[i], args[i]); } return value + "_" + parser.parseExpression(key).getValue(context, String.class); } }
3.在方法明上添加
@Cacheable(value="cacheUserInfo", key="#key", expire = 3600) public Object cacheUserInfo(String key) {}