spring boot 2.1.3 使用 mybatis redis cache 缓存

本贴最后更新于 2048 天前,其中的信息可能已经时过境迁

为了减少数据库访问频率,提高查询速度,今天讲一下 spring boot mybatis 怎么集成 redis 缓存。

第一步:添加 redis 相关 jar 包依赖

这里我只贴出集成 redis 缓存所需要的 jar 包,至于链接数据库,和基本的项目启动请参考
Spring boot 2 mybatis 配置

        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

至于 jar 包 spring-boot-starter-cache 至少在版本 2.1.3 可以不用引用,2.1.3 版本 jar 包 spring-boot-starter-data-redis 已经自带 cache 所需要的 jar 包,不用重复引用。

第二步:添加 redis 链接数据库配置文件

spring:
  # 数据库连接
  #datasource:
  #  password: 111111
  #  url: jdbc:mysql://120.77.241.43:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8
  #  username: root

  # redis
  redis:
    host: 127.0.0.1
    port: 6300
    password: 123
    # Redis数据库索引(默认为0)
    database: 0
    #连接超时时间(毫秒)
    timeout: 10000

    jedis: #一些常规配置
      pool:
        # 连接池中的最大空闲连接
        max-idle: 60
        # 连接池中的最小空闲连接
        min-idle: 30
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: 60000
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 200

第三步:添加 RedisConfig 配置类

@Configuration

@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Bean(name = "cacheKeyGenerator")
    @Primary//@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> CacheHashCode.of(params);
    }

    /**
     * spring boot 缓存默认配置
     * @param factory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        return RedisCacheManager.builder(factory)
                //默认缓存时间
                .cacheDefaults(getRedisCacheConfigurationWithTtl(60))
                .transactionAware()
                //自定义缓存时间
                .withInitialCacheConfigurations(getRedisCacheConfigurationMap())
                .build();
    }

    /**
     * 自定义缓存时间
     * @return
     */
    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
        redisCacheConfigurationMap.put("test", this.getRedisCacheConfigurationWithTtl(3000));
        return redisCacheConfigurationMap;
    }

    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(seconds))//定义默认的cache time-to-live.(缓存存储有效时间)
                .disableCachingNullValues()//静止缓存为空
                //此处定义了cache key的前缀, 避免公司不同项目之间的key名称冲突.
                .computePrefixWith(cacheName -> "api".concat(":").concat(cacheName).concat(":"))
                //定义key和value的序列化协议, 同时的hash key和hash value也被定义.
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(createJackson2JsonRedisSerializer()))
                //自定义key的生成策略, 将方法参数转换为hashcode, 作为redis key. 需要做两个事情, 一个是添加一个自定义的ConversionService, 另一个是需要自定义一个KeyGenerator.
                .withConversionService(new CacheKeyConversionService());
    }

    /**
     * 创建redisTemplate工具
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        template.setKeySerializer(new StringRedisSerializer());//设置key序列化类,否则key前面会多了一些乱码
        template.setValueSerializer(createJackson2JsonRedisSerializer());//设置value序列化
        template.setHashKeySerializer(createJackson2JsonRedisSerializer());//设置 hash key 序列化
        template.setHashValueSerializer(createJackson2JsonRedisSerializer());//设置 hash value 序列化
        template.setEnableTransactionSupport(true);//设置redis支持数据库的事务
        template.afterPropertiesSet();//初始化设置并且生效
        return template;
    }

    /**
     * 创建redis序列化
     * @return
     */
    private RedisSerializer<Object> createJackson2JsonRedisSerializer() {
        ObjectMapper objectMapper = new ObjectMapper();
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        return jackson2JsonRedisSerializer;
    }

}
public class CacheKeyConversionService implements ConversionService {
    @Override
    public boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType) {
        return true;
    }

    @Override
    public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
        return true;
    }

    @Nullable
    @Override
    public <T> T convert(@Nullable Object source, Class<T> targetType) {
        return (T) convert(source);
    }

    @Nullable
    @Override
    public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
        return convert(source);
    }

    private Object convert(Object source) {
        if (source instanceof CacheHashCode) {
            return ((CacheHashCode) source).hashString();
        }
        return CacheHashCode.of(source).hashString();
    }
}

第四步:在需要存入 redis 缓存的方法上添加注解

image.png

注解介绍
  • @Cacheable
    获取缓存 如果有缓存 直接返回
属性 类型 功能
value String[] 缓存的名称 和 cacheNames 功能一样
cacheNames String[] 缓存的名称和 value 功能一样
key String 缓存 key 的值、默认是以所有的参数作为 key、也可以直接配置 keyGenerator
keyGenerator String 缓存 key 的生成器
cacheManager String 配置使用那个缓存管理器、和 cacheResolver 排斥
cacheResolver String 定义使用那个拦截器、和 cacheManager 互斥
condition String 根据 spel 表达式来可以配置什么条件下进行缓存 默认全部缓存
unless String 和 condition 相反
sync boolean 是否开启同步功能、默认不开启
  • @CachePut
    执行并且更新缓存相关 不管如何 肯定会执行方法 然后返回 这样可以更新缓存的内容
属性 类型 功能
value String[] 缓存的名称 和 cacheNames 功能一样
cacheNames String[] 缓存的名称和 value 功能一样
key String 缓存 key 的值、默认是以所有的参数作为 key、也可以直接配置 keyGenerator
keyGenerator String 缓存 key 的生成器
cacheManager String 配置使用那个缓存管理器、和 cacheResolver 排斥
cacheResolver String 定义使用那个拦截器、和 cacheManager 互斥
condition String 根据 spel 表达式来可以配置什么条件下进行缓存 默认全部缓存
unless String 和 condition 相反
  • @CacheEvict
    删除缓存相关
属性 类型 功能
value String[] 缓存的名称 和 cacheNames 功能一样
cacheNames String[] 缓存的名称和 value 功能一样
key String 缓存 key 的值、默认是以所有的参数作为 key、也可以直接配置 keyGenerator
keyGenerator String 缓存 key 的生成器
cacheManager String 配置使用那个缓存管理器、和 cacheResolver 排斥
cacheResolver String 定义使用那个拦截器、和 cacheManager 互斥
condition String 根据 spel 表达式来可以配置什么条件下进行缓存 默认全部缓存
allEntries boolean 是否删除所有键的缓存 默认不删除
beforeInvocation boolean 是否在调用此方法前 删除缓存
  • @CacheConfig
    在类级别统一的配置缓存公共配置
属性 类型 功能
cacheNames String[] 缓存的名称和 value 功能一样
keyGenerator String 缓存 key 的生成器
cacheManager String 配置使用那个缓存管理器、和 cacheResolver 排斥
cacheResolver String 定义使用那个拦截器、和 cacheManager 互斥
  • @EnableCaching
    开启缓存以及缓存的全局配置
属性 类型 功能
proxyTargetClass boolean 是否要基于 cglib 生成代理去实现缓存
mode AdviceMode 配置那种模式去实现缓存、默认是 AdviceMode.PROXY 可以切换为 AdviceMode#ASPECTJ
order int 设置缓存管理器执行的顺序
  • @Caching
    对多个缓存组的配置
属性 类型 功能
cacheable Cacheable 配置获取缓存相关的配置
put CachePut 配置如何更新缓存的相关配置
evict CacheEvict 配置如何删除缓存的相关配置

注解介绍引用: https://www.jianshu.com/p/fd950f65aec7

第五步:在启动类配置开启缓存

image.png

第六步:运行查看效果

controller

image.png
查看 redis 客户端存储的数据

image.png
image.png

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    942 引用 • 1459 回帖 • 31 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...