• SpringBoot 整合redis实现缓存 记录@CachePut值为1


    一:先新增redis配置

     1 #redis
     2 spring.cache.type=REDIS
     3 spring.redis.database=0
     4 spring.redis.host=127.0.0.1
     5 pring.redis.password=
     6 spring.redis.port=6379
     7 spring.redis.pool.max-idle=8
     8 spring.redis.pool.min-idle=0  
     9 spring.redis.pool.max-active=100 
    10 spring.redis.pool.max-wait=-1
    11 #redis

    二:添加redis的配置类

    package com.gh.redis;
    
    
    import java.lang.reflect.Method;
    
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.annotation.CachingConfigurerSupport;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.cache.interceptor.KeyGenerator;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    @Configuration
    @EnableCaching
    public class RedisConfig extends CachingConfigurerSupport {
        /*定义缓存数据 key 生成策略的bean
        包名+类名+方法名+所有参数
        */
        @Bean
        public KeyGenerator wiselyKeyGenerator(){
            return new KeyGenerator() {
                @Override
                public Object generate(Object target, Method method, Object... params) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(target.getClass().getName());
                    sb.append(method.getName());
                    for (Object obj : params) {
                        sb.append(obj.toString());
                    }
                    return sb.toString();
                }
            };
     
        }
     
        /*要启用spring缓存支持,需创建一个 CacheManager的 bean,CacheManager 接口有很多实现,这里Redis 的集成,用 RedisCacheManager这个实现类
        Redis 不是应用的共享内存,它只是一个内存服务器,就像 MySql 似的,
        我们需要将应用连接到它并使用某种“语言”进行交互,因此我们还需要一个连接工厂以及一个 Spring 和 Redis 对话要用的 RedisTemplate,
        这些都是 Redis 缓存所必需的配置,把它们都放在自定义的 CachingConfigurerSupport 中
         */
        @Bean
        public CacheManager cacheManager(
                @SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
            RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
    //        cacheManager.setDefaultExpiration(60);//设置缓存保留时间(seconds)
            return cacheManager;
        }
     
        //1.项目启动时此方法先被注册成bean被spring管理
        @Bean
        public RedisTemplate<String, String> redisTemplate(
                RedisConnectionFactory factory) {StringRedisTemplate template = new StringRedisTemplate(factory);
            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;
        }
    }

    三:redis的三个常用注解 @Cacheable  @CacheEvict  @CachePut

      1:@Cacheable:当重复使用相同参数调用方法的时候,方法本身不会被调用执行,即方法本身被略过了,取而代之的是方法的结果直接从缓存中找到并返回了。

      实验:在业务逻辑实现方法上加上次注解

      其中value指的是要放在哪一个数据缓存里面

        key指的就是一个键

        @Override
        @Cacheable(value="db0",key="T(String).valueOf(#userid)")//把userid转换为string类型的
        public List<GhTest> getGhTestByID(int userid) {
            // TODO Auto-generated method stub
            System.out.println("aaaaaaa");
            return dao.getGhTestByID(userid);
        }

       对接口进行测试

       执行第一次控制台输出aaaaa        redis里面新建一个键值对

       

      再次测试,则不再输出aaaaa 说明数据是在缓存中所取。运行的步骤其实也就是,当@Cacheable接收到key value的时候先在value中找是不是存在key,如果不存在则在value中新建key 数据值为这个方法的返回值。如果存在则方法不执行从缓存中读取值。

      2:@CacheEvict

      

    1 @Override
    2     @CacheEvict(value = "db0", key ="T(String).valueOf(#userid)")
    3     public int deleteTest(int userid) {
    4         // TODO Auto-generated method stub
    5         return dao.deleteTest(userid);
    6     }

      使用接口测试发现,会删除掉数据库和缓存里面的值。可以在@CacheEvict 里面添加condition 表达式,让其满足什么条件的时候才删除缓存。

      3:@CachePut

      在测试这个修改的时候我遇到了问题,那就是我们平常写的修改和添加返回值一般都是int类型的,也就倒置了缓存里面存的值都是添加或者是修改的行数,并不是真实的数据。

      例如,

    1     @Override
    2     @CachePut(value = "db0", key ="T(String).valueOf(#test.userid)")
    3     public int updateTest(GhTest test) {
    4         // TODO Auto-generated method stub
    5         return dao.updateTest(test);
    6     }

      测试新增一条记录,userid为20,查看发现redis缓存里面是1,而不是userid为20的数据记录

     

      

      上面也说了,redis里面存的值,是方法的返回值,我们方法的返回值是int,是被影响的行数。所以会存进去1,那要对方法进行修改。

      解决方案就是,新建方法,把新增或者修改和查询结合这使用。

     1 @Override
     2     @CachePut(value = "db0", key ="T(String).valueOf(#test.userid)")
     3     public List<GhTest> insertTest2(GhTest test) {
     4         // TODO Auto-generated method stub
     5         insertTest(test);
     6         List<GhTest> list=getGhTestByID(test.getUserid());
     7         return list;
     8     }
     9     @Override
    10     @CachePut(value = "db0", key ="T(String).valueOf(#test.userid)")
    11     public List<GhTest> updateTest2(GhTest test) {
    12         // TODO Auto-generated method stub
    13         updateTest(test);
    14         List<GhTest> list=getGhTestByID(test.getUserid());
    15         return list;
    16     }

      再次进行测试,先对20那条记录进行修改,在进行id查询,如果不通过数据库查询就说明成功了。

      发现缓存中的值已经被修改,而且根据id查询也是通过缓存查询。

  • 相关阅读:
    Android导入自定义的jar包时出现 E/AndroidRuntime(486): java.lang.NoClassDefFoundError错误
    cocos2d-x认识之旅
    ASP.Net MVC Filter验证用户登录
    RHEL6安装调试过程中遇到的问题集
    java8新增特性(二)----函数式接口(Functional)
    京东云、新浪微博等专家畅谈Docker未来格局:开放与竞争(上)
    Activity启动模式的深入分析
    ShopEx 中规格属性添加时,自己主动计算其相应的销售价格,同一时候注意模板中的变量间的计算
    【天气APP】之桌面时钟witget组件
    xcode6.3 模版位置
  • 原文地址:https://www.cnblogs.com/GH0522/p/9437080.html
Copyright © 2020-2023  润新知