Redis——(7)redis作为mybatis缓存整合&二级缓存的整合

1.作为mybits的缓存整合 

    1)用户第一次访问的时候获取数据库的值,再次访问时直接从缓存中获取数据

      2)设置缓存过期时间

      3)项目8080端口是对外端口(向外部暴露的端口),区别于内部进程号,查内部端口用ps -ef|grep port,查外部端口用lsof -i:port

判断进程是否正常启动

启动会有一段时间datasource

结果:

 

先从缓存中拿数据,找不到再从DB中刷数据

2.作为mybits的二级缓存的整合

 (1)springboot cache的使用:可以结合redis、ehcache等缓存

之前的操作;1)先到redis缓存中去取值

                      2)如果找不到到db中去取值

                      3)将db中的值刷到缓存

这3个步骤都是固定的所以就有了cache

        一级缓存是:sqlSession,sql建立连接到关闭连接的数据缓存

        二级缓存是:全局

   @CacheConfig(cacheNames="userInfoCache")  在同个redis里面必须唯一

   @Cacheable(查) :

   来划分可缓存的方法 - 即,结果存储在缓存中的方法,以便在后续调用(具有相同的参数)时,返回缓存中的值而不必实际执行该方法

@CachePut(修改、增加) :

    当需要更新缓存而不干扰方法执行时,可以使用@CachePut注释。也就是说,始终执行该方法并将其结果放入缓存中(根据@CachePut选项)

    @CacheEvict(删除) :

     对于从缓存中删除陈旧或未使用的数据非常有用,指示缓存范围内的驱逐是否需要执行而不仅仅是一个条目驱逐

    (2)springboot cache的整合步骤:

      1)引入pom.xml依赖:

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
   </dependency>

       2)开启缓存注解: @EnableCaching(RedisConfig类           配置类)

       3)在方法上面加入SpEL         

   @CacheConfig(cacheNames="userInfoCache")  在同个redis里面必须唯一             指定cache的名称       

@Cacheable(查) :

   来划分可缓存的方法 -

即,结果存储在缓存中的方法,以便在后续调用(具有相同的参数)时,返回缓存中的值而不必实际执行该方法

@CachePut(修改、增加) :

    当需要更新缓存而不干扰方法执行时,可以使用@CachePut注释。

也就是说,始终执行该方法并将其结果放入缓存中(根据@CachePut选项)

@CacheEvict(删除) :

     对于从缓存中删除陈旧或未使用的数据非常有用,指示缓存范围内的驱逐是否需要执行而不仅仅是一个条目驱逐

结果:

@Service
@CacheConfig(cacheNames="userInfoCache") // 本类内方法指定使用缓存时,默认的名称就是userInfoCache
@Transactional(propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception.class)
public class UserService {

    @Autowired
    private UserMapper userMapper;

    // 因为必须要有返回值,才能保存到数据库中,如果保存的对象的某些字段是需要数据库生成的,
    //那保存对象进数据库的时候,就没必要放到缓存了
    @CachePut(key="#p0.id")  //#p0表示第一个参数
    //必须要有返回值,否则没数据放到缓存中
    public User insertUser(User u){
        this.userMapper.insert(u);
        //u对象中可能只有只几个有效字段,其他字段值靠数据库生成,比如id
        return this.userMapper.find(u.getId());
    }


    @CachePut(key="#p0.id")
    public User updateUser(User u){
        this.userMapper.update(u);
        //可能只是更新某几个字段而已,所以查次数据库把数据全部拿出来全部
        return this.userMapper.find(u.getId());
    }

    @Nullable
    @Cacheable(key="#p0") // @Cacheable 会先查询缓存,如果缓存中存在,则不执行方法
    public User findById(String id){
        System.err.println("根据id=" + id +"获取用户对象,从数据库中获取");
        Assert.notNull(id,"id不用为空");
        return this.userMapper.find(id);
    }



    @CacheEvict(key="#p0")  //删除缓存名称为userInfoCache,key等于指定的id对应的缓存
    public void deleteById(String id){
        this.userMapper.delete(id);
    }

    //清空缓存名称为userInfoCache(看类名上的注解)下的所有缓存
    //如果数据失败了,缓存时不会清除的
    @CacheEvict(allEntries = true)
    public void deleteAll(){
        this.userMapper.deleteAll();
    }


    @Nullable
    @Cacheable(value = "UserInfoList", keyGenerator = "simpleKeyGenerator") // @Cacheable 会先查询缓存,如果缓存中存在,则不执行方法
    public User findByIdTtl(String id){
        System.err.println("根据id=" + id +"获取用户对象,从数据库中获取");
        Assert.notNull(id,"id不用为空");
        return this.userMapper.find(id);
    }

}

提问:springboot cache 存在什么问题,

                                        第一,生成key过于简单,容易冲突       userinfoCache::3  (同一个redis只能有一个名称 ) key+参数  

                                        第二,无法设置过期时间,默认过期时间为永久不过期            (上面的3中方法)

                                        第三,配置序列化方式,默认的是序列化JDKSerialazable            jackson/json

如果不设置序列化的化可能会造成乱码等格式的问题

     (3)springboot cache自定义项

        1)自定义KeyGenerator  

         

        2)自定义cacheManager,设置缓存过期时间

        3)自定义序列化方式,Jackson

使用方法:(前两个)

@Configuration
@EnableCaching
public class RedisConfig {
    public RedisTemplate<String,String> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }
    @Bean
    public KeyGenerator simpleKeyGenerator() {
        return (o, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(o.getClass().getSimpleName());
            stringBuilder.append(".");
            stringBuilder.append(method.getName());
            stringBuilder.append("[");
            for (Object obj : objects) {
                stringBuilder.append(obj.toString());
            }
            stringBuilder.append("]");

            return stringBuilder.toString();
        };
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return new RedisCacheManager(
                RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
                this.getRedisCacheConfigurationWithTtl(600), // 默认策略,未配置的 key 会使用这个
                this.getRedisCacheConfigurationMap() // 指定 key 策略
        );
    }
/**
 *
 * 自定义某个key的过期时间
 */
    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
        redisCacheConfigurationMap.put("UserInfoList", this.getRedisCacheConfigurationWithTtl(100));
        redisCacheConfigurationMap.put("UserInfoListAnother", this.getRedisCacheConfigurationWithTtl(18000));
        return redisCacheConfigurationMap;
    }
    /**
     *
     * 自定义序列化的方式
     */
    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
        Jackson2JsonRedisSerializer<Object> 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);

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer)
        ).entryTtl(Duration.ofSeconds(seconds));

        return redisCacheConfiguration;
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智达教育‍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值