Caffeine配置:
@Slf4j
@Configuration
@EnableCaching
public class CaffeineCacheConfig {
private static final int MAX_REFRESH_COUNT = 2;
private static Cache<Object, Integer> caffeine = Caffeine.newBuilder()
.expireAfterAccess(Duration.ofMinutes(5))
.build();
@Bean
public CacheLoader<Object, Object> cacheLoader() {
return new CacheLoader<Object, Object>() {
@Nullable
@Override
public Object load(@NonNull Object o) throws Exception {
return null;
}
@Nullable
@Override
public Object reload(@NonNull Object key, @NonNull Object oldValue) throws Exception {
Integer refreshCount = caffeine.get(key, k -> 0);
if (refreshCount > MAX_REFRESH_COUNT) {
// 超过最大刷新次数时,强制重新加载
caffeine.invalidate(key);
return load(key);
}
caffeine.put(key, ++ refreshCount);
return oldValue;
}
};
}
}
pom依赖:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cache</groupId>
<artifactId>spring-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
使用的注解:
@Cacheable(value = "CACHE_DATA", key = "#id1+'-'+#id2", unless = "#result == null")
public Item getItemById(Long id) {
// ...
}
只有在方法返回结果不为空的情况下才会缓存结果(unless
属性的作用)。并且,缓存的 key 是根据方法参数 id
来生成的。
在 Spring 配置类或主应用程序类上添加 @EnableCaching 注解,以开启缓存支持。
确保配置了合适的缓存管理器(如 EhCache, Caffeine, Redis 等)。
如果使用的是 XML 配置,确保 <cache:annotation-driven /> 元素已添加到你的配置文件中。
application.xml上配置:
---
spring:
cache:
type: caffeine
caffeine:
spec: initialCapacity=500,maximumSize=5000,expireAfterWrite=600s,refreshAfterWrite=500s
cache-names: CACHE_DATA
-
type: CAFFEINE
:指定了应用程序使用 Caffeine 作为默认的缓存提供者。 -
initialCapacity=500
:- 这是缓存初始化时分配的容量大小。当缓存创建时,它将预先分配一定的空间来存储缓存条目。这个值表示缓存开始时可以容纳的条目数量。
-
maximumSize=5000
:- 设置了缓存的最大容量。一旦缓存中的条目数超过了这个数值,最旧的条目将会被移除(根据 LRU 或其他策略)以腾出空间给新的条目。
-
expireAfterWrite=600s
:- 定义了写入后过期时间。这意味着从一个条目被添加或更新后的那一刻起,经过 600 秒(10 分钟)之后,该条目将被视为过期,并在下次访问时被移除。
-
refreshAfterWrite=500s
:- 指定刷新间隔时间。这表示如果一个条目在写入后超过 500 秒未被访问,则会在下一次访问时尝试刷新其内容。注意,
refreshAfterWrite
并不会自动触发数据加载;它仅影响下一次访问时的行为。具体来说,只有当条目确实过期并且需要重新加载时才会发生刷新操作。
- 指定刷新间隔时间。这表示如果一个条目在写入后超过 500 秒未被访问,则会在下一次访问时尝试刷新其内容。注意,
2025-01-20 start:
redis缓存配置
pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
配置文件:RedisCacheConfig
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
/**
* spring-cache使用redis缓存配置
*/
@Slf4j
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
Jackson2JsonRedisSerializer<【返回的结果类】> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(【返回的结果类】);
RedisCacheConfiguration configuration = RedisCacheConfiguration
.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
// 过期:一天
.entryTtl(Duration.ofDays(1));
return RedisCacheManager
.builder(redisCacheWriter)
.cacheDefaults(configuration)
.build();
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
log.warn("Redis occur exception, use custom CacheErrorHandler to handle");
return new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
doHandleRedisErrorException(exception, key);
}
@Override
public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
doHandleRedisErrorException(exception, key);
}
@Override
public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
doHandleRedisErrorException(exception, key);
}
@Override
public void handleCacheClearError(RuntimeException exception, Cache cache) {
doHandleRedisErrorException(exception, null);
}
};
}
protected void doHandleRedisErrorException(RuntimeException exception, Object key) {
log.warn("Redis occur exception:key=[{}]", key, exception);
String redisKey = (String) key;
if (redisKey.contains("LOCK")) {
throw exception;
}
}
}
redis配置:RedisConfiguration
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis配置
* @author huangjuguan
* @date 2020/7/8.
*/
@Configuration
public class RedisConfiguration {
@Bean("objectRedisTemplate")
public RedisTemplate<String, Object> objectRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.setEnableTransactionSupport(true);
return redisTemplate;
}
}
使用同上
end