Spring中的缓存抽象
Spring中的缓存
Spring为不同的缓存提供一层抽象
- 为java方法增加缓存,缓存执行结果。下次相同的参数访问,直接从缓存取。
- 支持ConcurrentMap、EhCache、redis、Caffeine、JCache(JSR-7)
- 接口
- org.springframework.cache.Cache
- org.springframework.cache.CacheManager
对于需要集群的缓存,可以用支持分布式缓存的,如redis
缓存相关的注解
@EnableCaching
开启缓存支持
@Cacheble
方法缓存,没有的话,拿到方法值并存缓存。有的话直接从缓存去。
@CacheEvict
缓存的清理
@CachePut
不管方法的执行情况,直接做缓存的设置
@Caching
缓存方法的打包,可以执行上述多个操作
@CacheConfig
缓存的设置,可以设置缓存的名字
@EnableCaching
于spring版本3.1起加入了该注解。如果你使用了这个注解,那么你就不需要在XML文件中配置cache manager了。
示例
下面是一个示例,通过注解添加对方法返回值的缓存、以及缓存清除。
配置文件
spring.cache.type=redis
# 程序启动时创建缓存名
#spring.cache.cache-names=count
#缓存的时间5s
spring.cache.redis.time-to-live=5000
spring.cache.redis.cache-null-values=false
演示类
@Slf4j
@Service
@CacheConfig(cacheNames = "count")
public class CountingService {
@CacheEvict
public void clearCount() {
}
@Cacheable
public int getNumber() {
log.error("Reading from cache.......");
return 1000;
}
}
@SpringBootApplication
@Slf4j
@EnableCaching(proxyTargetClass = true)
public class JedisDemoApplication implements ApplicationRunner {
@Autowired
private CountingService countingService;
public static void main(String[] args) {
SpringApplication.run(JedisDemoApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("Count: {}", countingService.getNumber());
for (int i = 0; i < 10; i++) {
if (i == 5){
countingService.clearCount();
}
log.info("time:{} Count: {}", i, countingService.getNumber());
}
}
}
-: Reading from cache.......
-: Count: 1000
-: time:0 Count: 1000
-: time:1 Count: 1000
-: time:2 Count: 1000
-: time:3 Count: 1000
-: time:4 Count: 1000
-: Reading from cache.......
-: time:5 Count: 1000
-: time:6 Count: 1000
-: time:7 Count: 1000
-: time:8 Count: 1000
-: time:9 Count: 1000
Spring Data Redis
配置与使用
Spring Data Redis是Spring Data系列的一部分,可以从Spring应用程序轻松配置和访问Redis。它提供了与store交互的低级(RedisTemplate)和高级(ListOperations)抽象,使用户可以对基础设施少操点心。
支持 Jedis和Lettuce, 2.X以后默认实现是Lettuce
(JRedis和SRP已被标记为过期)。
使用:需要引入依赖spring-boot-starter-cache
和spring-boot-starter-data-redis
。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
修改相关配置:
spring.cache.type=redis
# 程序启动时创建缓存名
spring.cache.cache-names=count
#缓存的时间5s
spring.cache.redis.time-to-live=5000
spring.cache.redis.cache-null-values=false
spring.redis.host=localhost
spring.redis.port=6379
其他代码与缓存相关的注解 > 示例相同,可以看到数据直接存到redis中了。
如果存储class,需要实现Serializable
以便进行序列化工作。
@Data
public class HUser implements Serializable {
private String id;
private String nickName;
private Integer age;
}
RedisTemplate
redisTemplate.opsForXXX系列:
非绑定key操作
- ValueOperations<K, V> opsForValue();
- <HK, HV> HashOperations<K, HK, HV> opsForHash();
- ListOperations<K, V> opsForList();
- SetOperations<K, V> opsForSet();
- ZSetOperations<K, V> opsForZSet();
绑定key操作,若以bound开头,则意味着在操作之初就会绑定一个key,后续的所有操作便默认认为是对该key的操作
- BoundValueOperations<K, V> boundValueOps(K key);
- <HK, HV> BoundHashOperations<K, HK, HV> boundHashOps(K key);
- BoundListOperations<K, V> boundListOps(K key);
- BoundSetOperations<K, V> boundSetOps(K key);
- BoundZSetOperations<K, V> boundZSetOps(K key);
示例1:简单的存取
配置文件
spring.redis.host=localhost
spring.redis.port=6379
测试类
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Bean
public RedisTemplate<String, Object> redisObjectTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
private void redisTemplateSimpleDemo() {
Map<String, Object> properties = new HashMap<>();
properties.put("123", "hello");
properties.put("456", "world");
properties.put("abc", 456);
redisTemplate.opsForHash().putAll("hash", properties);
redisTemplate.expire("hash",20, TimeUnit.SECONDS);
Map<Object, Object> ans = redisTemplate.opsForHash().entries("hash");
log.info(ans.toString());
}
示例2:存储class,以及lettuce相关配置
配置文件
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.url=redis://user:password@localhost:6379
#Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
#spring.redis.database=0
#需要配置bean似乎
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
#连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
自定义的class需要支持implements Serializable
@Data
public class HUser implements Serializable {
private String id;
private String nickName;
private Integer age;
}
因为配置了lettuce
相关参数而与示例1稍有区别:
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Bean
public RedisTemplate<String, HUser> redisUserTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, HUser> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
public LettuceClientConfigurationBuilderCustomizer customizer() {
return builder -> builder.readFrom(ReadFrom.MASTER_PREFERRED);
}
private void redisAddEntity() {
HUser user = new HUser();
user.setAge(11);
user.setId("01");
user.setNickName("Ken");
redisUserTemplate.opsForValue().set("user:ken", user);
HUser u2 = redisUserTemplate.opsForValue().get("user:ken");
log.info(u2.toString());
}
示例2: cluster和sentinel
TODO:待完善
其他
代码示例
相关参考