SSM项目中使用Redis缓存

来源:互联网 发布:windows任务管理工具 编辑:程序博客网 时间:2024/05/29 23:23

适合使用缓存的数据:

1 很少更新的数据

2 经常被用到的数据

3 数据量不大的数据


缓存控制

声明3个注解,对类或者方法是否支持缓存进行控制

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface MyCacheable {    int expire() default 600;//缓存过期时间,单位秒,默认60}@Target(ElementType.METHOD)@Inherited@Retention(RetentionPolicy.RUNTIME)public @interface MyUseCache {}@Target(ElementType.METHOD)@Inherited@Retention(RetentionPolicy.RUNTIME)public @interface MyClearCache {}
MyCacheable注解标注在类上,控制这个类的方法时候可以使用MyUseCache和MyClearCache注解

MyUseCache注解标注在方法上,在执行方法之前,先从缓存尝试获取数据,如果获取了,直接返回数据,如果没有获取到,执行方法进行查询,并且把查询到的数据放入缓存

MyClearCache注解标注在方法上,清空缓存


使用原则

会更新数据的操作都清理缓存

对于有关联关系的表,当相关联的表进行了更新操作时,会出现缓存数据和数据库数据不一致,通过设置缓存过期时间来解决。缓存过期时间根据数据不一致可接受时间决定

由于需要支持过期时间,需要每条缓存使用一个独立的key,为了对一个表的缓存进行全部删除,需要保证同一个类的缓存的key的前缀一致

value是json格式的字符串数据,如果查询方法的返回值不符合json格式,则不能使用缓存


实现缓存的AOP代码


@Aspectpublic class CacheAspect {    @Pointcut("@target(com.my.annotation.MyCacheable)")    private void cacheable() {    }    @Pointcut("@annotation(com.my.annotation.MyUseCache)")    private void useCache() {    }    @Pointcut("@annotation(com.my.annotation.MyClearCache)")    private void clearCache() {    }    @SuppressWarnings("all")    @Around("cacheable() && useCache()")    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {        //目标类Class对象        Class targetClass = joinPoint.getTarget().getClass();        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();        String key = createKey(joinPoint);        String value = JedisUtils.get(key);//从缓存中取数据        //如果缓存数据不为空,则直接使用缓存数据        if (!CommonUtils.isEmpty(value)) {            //方法返回值类型            Class returnType = ReflectUtils.getActualReturnType(targetClass, method);            //方法返回值类型的泛型类型            Class[] parametricTypes = ReflectUtils.getActualParametricTypeOfReturnType(targetClass, method);            return JsonUtils.toBean(value, returnType, parametricTypes);        } else {            //如果执行到这里就说明缓存里面没有数据,则执行正常逻辑(从数据库中查询数据)            Object returnObject = joinPoint.proceed();            MyCacheable cacheable = (MyCacheable) targetClass.getAnnotation(MyCacheable.class);            //把数据存入缓存            JedisUtils.setex(key, cacheable.expire(), JsonUtils.toJson(returnObject));            return returnObject;        }    }    @After("cacheable() && clearCache()")    public void after(JoinPoint joinPoint) {        //清空和此key前缀匹配的所有缓存        JedisUtils.del(createKeyPatternForDelete(joinPoint));    }    //生成要删除的redis key的正则表达式    private String createKeyPatternForDelete(JoinPoint joinPoint) {        StringBuilder keyPattern = new StringBuilder();        keyPattern.append("cache_").append(joinPoint.getTarget().getClass().getName()).append("_*");        return keyPattern.toString();    }    private String createKey(JoinPoint joinPoint) {        StringBuilder key = new StringBuilder();//redis缓存key的前缀        key.append("cache_").append(joinPoint.getTarget().getClass().getName()).append("_");        String signature = joinPoint.getSignature().toString();        signature = signature.substring(signature.lastIndexOf('.') + 1);        key.append(signature).append("_");        Object[] args = joinPoint.getArgs();        if (args != null && args.length > 0) {            String argsStr = JsonUtils.toJson(args);            //把:替换为_,避免生成命名空间            argsStr = argsStr.replaceAll(":", "_");            key.append(argsStr);        }        return key.toString();    }}







原创粉丝点击