【7】Spring Boot 3 集成组件:缓存组件 spring cache + spring data redis

目录

个人主页: 【⭐️个人主页

需要您的【💖 点赞+关注】支持 💯


【7】Spring Boot 3 集成组件:缓存组件 spring cache + spring data redis

📖 本文核心知识点:

  • spring cache 抽象和注解
  • cache 支持的缓存类型
  • spring cache + spring data redis 配置
  • redis序列化

本章使用的spring版本
spring boot version: 3.1.5

什么是缓存抽象

  1. 缓存抽象的作用
  2. spring缓存的声明式注解
  3. spring缓存的生成key策略和如何自定义keyGenerator
  4. 缓存支持的后端类型

声明式注解

Spring 缓存注解 说明
@Cacheable 触发缓存填充。
@CacheEvict 触发缓存退出。
@CachePut 在不干扰方法执行的情况下更新缓存。
@Caching 将多个缓存操作重新组合到一个方法上。
@CacheConfig 在类级别共享一些常见的与缓存相关的设置。

JSR-107对应

Spring 缓存注解 JSR-107 备注
@Cacheable @CacheResult 相当相似。 可以缓存特定的异常并强制 无论缓存的内容如何,都执行该方法。@CacheResult
@CachePut @CachePut 当 Spring 使用方法调用的结果更新缓存时,JCache 要求将其作为注释的参数传递。 由于这种差异,JCache 允许在 实际方法调用。@CacheValue
@CacheEvict @CacheRemove 相当相似。 支持有条件逐出,当 方法调用会导致异常。@CacheRemove
@CacheEvict(allEntries=true) @CacheRemoveAll 看。@CacheRemove
@CacheConfig @CacheDefaults 允许您以类似的方式配置相同的概念。

SpEL上下文数据

名称 位置 描述 示例
methodName root对象 当前被调用的方法名 #root.methodname
method root对象 当前被调用的方法 #root.method.name
target root对象 当前被调用的目标对象实例 #root.target
targetClass root对象 当前被调用的目标对象的类 #root.targetClass
args root对象 当前被调用的方法的参数列表 #root.args[0]
caches root对象 当前方法调用使用的缓存列表 #root.caches[0].name
Argument Name 执行上下文 当前被调用的方法的参数,如findArtisan(Artisan artisan),可以通过#artsian.id获得参数 #artsian.id
result 执行上下文 方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false) #result

引入依赖

groovy 复制代码
    implementation 'org.springframework.boot:spring-boot-starter-cache'

添加启用缓存注解@EnableCaching

java 复制代码
@SpringBootApplication(scanBasePackages = {"com.kongxiang"})
@EnableAutoConfiguration
@EnableCaching
public class StudySpring3Application {

	public static void main(String[] args) {
		SpringApplication.run(StudySpring3Application.class, args);
	}
}

cache 支持的缓存类型

spring cache支持的缓存类型

查看类org.springframework.boot.autoconfigure.cache.CacheType

java 复制代码
public enum CacheType {

	/**
	 * Generic caching using 'Cache' beans from the context.
	 */
	GENERIC,

	/**
	 * JCache (JSR-107) backed caching.
	 */
	JCACHE,

	/**
	 * Hazelcast backed caching.
	 */
	HAZELCAST,

	/**
	 * Couchbase backed caching.
	 */
	COUCHBASE,

	/**
	 * Infinispan backed caching.
	 */
	INFINISPAN,

	/**
	 * Redis backed caching.
	 */
	REDIS,

	/**
	 * Cache2k backed caching.
	 */
	CACHE2K,

	/**
	 * Caffeine backed caching.
	 */
	CAFFEINE,

	/**
	 * Simple in-memory caching.
	 */
	SIMPLE,

	/**
	 * No caching.
	 */
	NONE

}

缓存类型配置

NONE

无缓存

yml 复制代码
spring:
  cache:
    type: NONE

SIMPLE

内存缓存

yml 复制代码
spring:
  cache:
    type: SIMPLE

REDIS

Redis 缓存

yml 复制代码
spring:
  cache:
    type: REDIS
  data:
    redis:
      host: '127.0.0.1'
      username:
      port: 6379
      password:
      database: 1
      lettuce:
        pool:
          enabled: true
          max-active: 8
          max-wait: 1000
          max-idle: 8
      connect-timeout: 5000
自定义配置

默认情况下会有两个模板类被注入Spring IoC供我们使用,需要个性化配置来满足实际的开发。

一个是RedisTemplate<Object, Object>,主要用于对象缓存,其默认使用JDK序列化,我们需要更改其序列化方式解决一些问题,比如Java 8日期问题JSON序列化问题。需要我们重写一下。

  1. RedisTemplate自定义配置
java 复制代码
 @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // 使用Jackson2JsonRedisSerialize 替换默认序列化
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = initJacksonSerializer();
        // 设置value的序列化规则和 key的序列化规则
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
    /**
     * 处理redis序列化问题
     * @return Jackson2JsonRedisSerializer
     */
    private Jackson2JsonRedisSerializer<Object> initJacksonSerializer() {
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //以下替代旧版本 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
        //bugFix Jackson2反序列化数据处理LocalDateTime类型时出错
        om.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);
        // java8 时间支持
        om.registerModule(new JavaTimeModule());
        return new Jackson2JsonRedisSerializer<>(om,Object.class);
    }
  1. 缓存管理器自定义配置
    使用Spring Cache做缓存的时候,有针对不同的key设置不同过期时间的场景。比如Jwt Token我想设置为一周过期,而验证码我想设置为五分钟过期。这个怎么实现呢?需要我们个性化配置RedisCacheManager。首先我通过枚举来定义这些缓存及其TTL时间

我们通过向Spring IoC分别注入RedisCacheConfigurationRedisCacheManagerBuilderCustomizer来个性化配置

java 复制代码
 /**
     * Redis cache configuration.
     *
     * @param redisTemplate the redis template
     * @return the redis cache configuration
     */
    @Bean
    public RedisCacheConfiguration redisCacheConfiguration(RedisTemplate<Object, Object> redisTemplate, CacheProperties cacheProperties) {
        // 参见 spring.cache.redis
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                // 缓存的序列化问题
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(redisTemplate.getValueSerializer()));

        if (redisProperties.getTimeToLive() != null) {
            // 全局 TTL 时间
            redisCacheConfiguration = redisCacheConfiguration.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            // key 前缀值
            redisCacheConfiguration = redisCacheConfiguration.prefixCacheNameWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            // 默认缓存null值 可以防止缓存穿透
            redisCacheConfiguration = redisCacheConfiguration.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            // 不使用key前缀
            redisCacheConfiguration = redisCacheConfiguration.disableKeyPrefix();
        }
        return redisCacheConfiguration;
    }

    /**
     * Redis cache manager 个性化配置缓存过期时间.
     *
     * @return the redis cache manager builder customizer
     */
    @Bean
    public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer(RedisCacheConfiguration redisCacheConfiguration) {
        return builder -> builder.cacheDefaults(redisCacheConfiguration);
    }

CAFFEINE

引入依赖

groovy 复制代码
    implementation 'com.github.ben-manes.caffeine:caffeine:3.1.8'

修改配置

yml 复制代码
spring:
  cache:
    type: CAFFEINE

直接启动即可

Hazelcast

...

总结

spring cache 缓存抽象加上spring data包和spring boot autoconfig 配置包的能力,可以快速接入一个具体的缓存实现。redis是我们公司基本使用的缓存策略。所以针对redis的一些自定义配置,通过 java bean的方式实现。着重强调一下。

相关推荐
choice of13 分钟前
SpringMVC通过注解实现全局异常处理
java·后端·spring
单线程bug13 分钟前
Spring Boot中Filter与Interceptor的区别
java·spring boot·后端
小蒜学长19 分钟前
基于uni-app的蛋糕订购小程序的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·小程序·uni-app
麦麦大数据1 小时前
J002 Vue+SpringBoot电影推荐可视化系统|双协同过滤推荐算法评论情感分析spark数据分析|配套文档1.34万字
vue.js·spring boot·数据分析·spark·可视化·推荐算法
二掌柜,酒来!7 小时前
完美解决:应用版本更新,增加字段导致 Redis 旧数据反序列化报错
redis·spring·bootstrap
期待のcode8 小时前
Spring框架1—Spring的IOC核心技术1
java·后端·spring·架构
鼠鼠我捏,要死了捏8 小时前
Spring Boot Actuator自定义指标与监控实践指南
spring boot·监控·actuator
上官浩仁9 小时前
springboot excel 表格入门与实战
java·spring boot·excel
EkihzniY10 小时前
OCR 识别表现好坏离不开什么?
缓存
小熊h10 小时前
redis 集群——redis cluster(去中心化)
redis·去中心化