@CacheEvict支持指定key值,进行缓存失效
2021-02-02 本文已影响0人
清蒸三文鱼_
背景
Spring Cache默认的KeyGenerator,在注解中必须指定key(不指定时会以方法中的参数作为key的内容)。如果同个缓存的操作不同的方法, 一个新增另一个失效,那么@CacheEvict和@Cacheable注解上的key必须要保持一致, 这时候如果方法的参数不一致,会导致缓存的操作失败,因为这时候完整的key已经不一致了
![](https://img.haomeiwen.com/i18249296/b6e6e513f3b715d7.png)
maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
application.yml
spring:
redis:
host: localhost
port: 6379
Code
增删查测试类
@Service
public class TestService {
HashMap<String, Object> data = new HashMap<>();
{
data.put("1", "1_x");
data.put("2", "2_x");
}
@CacheEvict(value = "get", key = EMPTY_KEY)
public void put(String key, Object value) {
data.put(key, value);
}
@CacheEvict(value = "get", key = EMPTY_KEY)
public void remove(String key) {
data.remove(key);
}
@Cacheable(value = "get", key = EMPTY_KEY)
public HashMap<String, Object> get() {
return data;
}
}
Redis缓存管理配置类
缓存值的写入默认是使用二进制的, 这里改用jackson进行序列化; 有个地方需要注意, EMPTY_KEY
需要符合spring-expression
表达式的规范, 否则会报错
![](https://img.haomeiwen.com/i18249296/628b5f67173e072f.png)
@EnableCaching
@Configuration
@ComponentScan(basePackages = "my.test")
public class RedisCacheConfig extends CachingConfigurerSupport {
public static final String EMPTY_KEY = "'DEFAULT'";
private static final SimpleKeyGenerator SIMPLE_KEY_GENERATOR = new SimpleKeyGenerator();
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Autowired
private ObjectMapper objectMapper;
@Override
@Bean
public CacheManager cacheManager() {
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
serializer.setObjectMapper(objectMapper);
RedisSerializationContext.SerializationPair val = RedisSerializationContext.SerializationPair.fromSerializer(serializer);
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(val);
// defaultCacheConfig.entryTtl(Duration.ofSeconds(120));
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(defaultCacheConfig).build();
}
@Override
@Bean
public KeyGenerator keyGenerator() {
return (o, m, params) -> {
CacheEvict cacheEvict = m.getAnnotation(CacheEvict.class);
if (Objects.nonNull(cacheEvict) && EMPTY_KEY.equals(cacheEvict.key())) {
return EMPTY_KEY;
}
if (params.length == 0) {
return EMPTY_KEY;
}
return SIMPLE_KEY_GENERATOR.generate(o, m, params);
};
}
}
SpringBoot入口类和缓存测试类
@EnableCaching
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Component
class CacheRun implements CommandLineRunner {
@Autowired
TestService testService;
@Override
public void run(String... args) throws Exception {
HashMap<String, Object> d1 = testService.get();
testService.remove("1");
HashMap<String, Object> d2 = testService.get();
assert !d2.containsKey("1");
testService.put("3", "3_x");
HashMap<String, Object> d3 = testService.get();
assert d3.containsKey("3");
}
}
}
结果
![](https://img.haomeiwen.com/i18249296/614c53236ffaec82.png)