原创

博客缓存的那些事?

一、写在前面

最近博客的前端展示页面基本高一段落了,切换一下数据源,看看连接生产的数据试试效果,结果不是很理想,光一个首页就触发很多sql语句,为了能够缩短首页的加载时间,特做了几点优化。 1543214753(1)
  • 系统启动时,加载常用的变量
  • service做了一层通用的缓存拦截控制

二、系统启动加载缓存

@Component @Order(1) public class CacheInit implements CommandLineRunner { private static final Logger log = LoggerFactory.getLogger(CacheInit.class); @Autowired private RedisTemplate<String,Object> redisTemplate; @Autowired private WpOptionsService wpOptionsService; /** * @param args * @throws Exception * @see org.springframework.boot.CommandLineRunner#run(java.lang.String[]) */ @Override public void run(String... args) throws Exception { log.info(">>>>>>>>>>>>>加载缓存数据开始<<<<<<<<<<<<<<<<<<<<<<"); Map<String,String> map= new HashMap<String,String>(); List<WpOptions> list =wpOptionsService.autoloadConfig(); for(WpOptions wpOptions:list){ if(!StringUtils.isEmpty(wpOptions.getOptionValue())){ map.put(wpOptions.getOptionName(), wpOptions.getOptionValue()); } } log.info("加载系统配置信息:"+list.size()); redisTemplate.opsForValue().set(RedisConstant.autoloadConfig, map); //Object test =redisTemplate.opsForValue().get("test"); //log.info("取出缓存数据:"+test.toString()); log.info(">>>>>>>>>>>>>初始化缓存数据 结束<<<<<<<<<<<<<<<<<<<<<<"); } }

三、Service实现通用缓存控制:

大概思路如下:
1.新增一个注解,针对特定的注解进行拦截 2.设置一个通用的key生成算法 3.对缓存进行逻辑的判断
新增一个注解@RedisCache,对有需要的缓存的方法进行添加设置
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface RedisCache { /** * 业务的名称 */ String value() default ""; /** * redis缓存的Key(默认类名-方法名-自定义key) */ String key() default ""; /** * 是否刷新缓存,默认false */ boolean flush() default false; /** * 缓存失效时间,默认30 */ long expire() default 30L; /** * 缓存时间单位,默认天 */ TimeUnit unit() default TimeUnit.DAYS; }
拦截代码
@Pointcut(value = "@annotation(cn.liuhaihua.web.annotation.RedisCache)") public void pointcut() { }
key通用的生成算法
/** * 获取切面缓存的key * * @param point * 当前切面执行的方法 * @param extra * 额外的参数 (非必选) * @param prefix * key前缀 (非必选) * @throws NoSuchMethodException */ public static String getKey(ProceedingJoinPoint point, String extra, String prefix) throws NoSuchMethodException { Method currentMethod = AspectUtil.getMethod(point); String methodName = currentMethod.getName(); StringBuilder key = new StringBuilder(); key.append(getKeyOfClassPrefix(point, prefix)); key.append("_"); key.append(methodName); key.append(getMethodParamsKey(point.getArgs())); key.append(null == extra ? "" : extra); return key.toString(); }
对拦截的方法进行缓存逻辑处理
@Around("pointcut()") public Object handle(ProceedingJoinPoint point) throws Throwable { Method currentMethod = AspectUtil.getMethod(point); //获取操作名称 RedisCache cache = currentMethod.getAnnotation(RedisCache.class); boolean flush = cache.flush(); if (flush) { String classPrefix = AspectUtil.getKeyOfClassPrefix(point, BIZ_CACHE_PREFIX); log.info("清空缓存 - {}*", classPrefix); redisService.delBatch(classPrefix); return point.proceed(); } //通用缓存 String key = AspectUtil.getKey(point, cache.key(), BIZ_CACHE_PREFIX); log.info("生成的KEY名字:{}", key); boolean hasKey = redisService.hasKey(key); if (hasKey) { try { log.info("{}从缓存中获取数据", key); return redisService.get(key); } catch (Exception e) { log.error("从缓存中获取数据失败!", e); } } //先执行业务 Object result = point.proceed(); redisService.set(key, result, cache.expire(), cache.unit()); log.info("{}从数据库中获取数据", key); return result; }
 

四、如何使用

代码如下
@Override @RedisCache public List<WpLinks> getLinks(String linkrel) { if(StringUtils.isEmpty(linkrel) ){ return wpLinksMapper.selectAll(); }else{ Example example = new Example(WpLinks.class); Criteria criteria = example.createCriteria(); criteria.andEqualTo("linkRel", LinkConstant.LINK_REL_FRIEND); return wpLinksMapper.selectByExample(example); } }
效果
INFO | 2018-11-26 14:06:57,264 | JWordpres-v2.0 | [http-nio-8090-exec-1-14] (c.l.w.a.RedisCacheAspect:70) | 生成的KEY名字:biz_cache_cn_liuhaihua_web_service_impl_WpLinksServiceImpl_getLinks('friend') INFO | 2018-11-26 14:06:57,281 | JWordpres-v2.0 | [http-nio-8090-exec-1-14] (c.l.w.a.RedisCacheAspect:74) | biz_cache_cn_liuhaihua_web_service_impl_WpLinksServiceImpl_getLinks('friend')从缓存中获取数据
正文到此结束
Loading...