SpringMvc使用Redis缓存

时间:2017-11-12 点击:622

缓存的目的就是为了减小对数据库的压力。学习缓存对于日后优化Web项目起到很大的作用

这里用我的博客做例子:SpringBoot整合的方式

这里就直接贴代码说明了。

# Redis settings
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.pool.max-idle=300
spring.redis.pool.max-active=600
spring.redis.pool.max-wait=1000

Bean配置

@SpringBootConfiguration
@EnableCaching //缓存开启注解
public class CacheConfig {

    private Logger logger = Logger.getLogger(CacheConfig.class.getName());

    //缓存管理器
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        //设置缓存过期时间 s为单位
        //缓存为20分钟过期
        cacheManager.setDefaultExpiration(1*60*20);
        return cacheManager;
    }


    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
        //设置redis 键值生成策略
        StringRedisTemplate template = new StringRedisTemplate(factory);
        //设置序列化工具
        //使用Json序列化的方式替换Jdk序列方式
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    //Key生成器
    //官方的Key不会生成类名方法名,可能导致Key重复的情况。
    @Bean(name = "cacheKeyGenerator")
    public KeyGenerator CacheKeyGenerator(){
        //缓存Key生成策略
        return (Object target, Method method, Object... params) ->  {
             StringBuilder key = new StringBuilder();
                key.append(target.getClass().getSimpleName()).append(".").append(method.getName()).append(":");
                if (params.length == 0) {
                    return key.append(NO_PARAM_KEY).toString();
                }
                for (Object param : params) {
                    if (param == null) {
                        logger.info("input null param for Spring cache, use default key={"+NULL_PARAM_KEY+"}" );
                        key.append(NULL_PARAM_KEY);
                    } else if (ClassUtils.isPrimitiveArray(param.getClass())) {
                        int length = Array.getLength(param);
                        for (int i = 0; i < length; i++) {
                            key.append(Array.get(param, i));
                            key.append(',');
                        }
                    } else if (ClassUtils.isPrimitiveOrWrapper(param.getClass()) || param instanceof String) {
                        key.append(param);
                    } else {
                        logger.info("Using an object as a cache key may lead to unexpected results. " +
                                "Either use @Cacheable(key=..) or implement CacheKey. Method is " + target.getClass() + "#" + method.getName());
                        key.append(param.hashCode());
                    }
                    key.append('-');
                }
                return key.toString();
        };
    }

}

缓存查询使用,我这里直接就定义在接口

@Cacheable(cacheNames = "articleList",keyGenerator="cacheKeyGenerator")
ArticleList  getIndexItem(Integer page);

@Cacheable(cacheNames = "articleList",keyGenerator="cacheKeyGenerator") //如果有缓存就直接返回,没有缓存就执行方法,再把结果添加进缓存
ArticleList  getByCategoryItem(Integer categoryId,Integer page);

@Cacheable(cacheNames ="articleBean", keyGenerator="cacheKeyGenerator")
Map<String,Article> show(Integer id);

//虽然cacheNames 相同,但是生成的Key不同。
//缓存其实就是使用的Aop方式拦截 .他会根据生成的Key去查缓存,而cacheNames 方便其他业务管理缓存也就相当于Id

缓存更新

@CacheEvict(cacheNames="articleBean", allEntries=true) // 对articleBean的缓存进行清除操作 方便下次查询更新缓存
@Override
int insert(Article article);

@CacheEvict(cacheNames="articleBean", allEntries=true)
@Override
int updateByPrimaryKey(Article article);

其他的注解

@CachePut  //缓存同时要生成同时不影响执行的方法
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary") }) //可以同时使用多个@CacheEvict
@CacheConfig //在类级别上减轻缓存繁琐的配置 //比如说Key生成 cacheNames...


注意的问题

  1. 缓存建立的位置在Service层

  2. Key同名相当于执行的同一个方法。容易出现问题

  3. 不要在同类的方法中调用缓存生成的方法,这样会造成缓存失效。原因是:生成缓存的类会被Spring代理,同类中调用生成缓存的方法会导致AOP拦截失效。所以要避免这样的问题


参阅

https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache

标签:java 分类:知识共享

上一篇: 前程无忧(51job)招聘数据web端分析查询工具

下一篇: SpringMvc整合Lucene.入门实例