Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。Redis本身是一个内存数据库,在应用中可以充当缓存,提高系统数据查询性能。
缓存一般用于在较短的时间段对相同数据频繁读取的场合,将读取频度较高的数据放入缓存,直接从缓存取数据,以提高效率。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
# 声明缓存类型
spring.cache.type=redis
# redis缓存过期时间
spring.cache.redis.time-to-live=600000
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=20
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000
@EnableCaching
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
这个Bean默认使用JdkSerializationRedisSerializer进行序列化,即key, value需要实现Serializable接口
Car car = new Car(1L, "宝马", "BMW");
//存放数据
redisTemplate.opsForValue().set("car1", car);
//取数据
Car car1 = (Car) redisTemplate.opsForValue().get("car1");
存入redis数据如图所示
StringRedisTemplate默认使用的是StringRedisSerializer序列化。这个bean的key,value都为String,所以要存储复杂数据时,要先将数据转换为String类型,一般转为json格式进行读取。
Car car = new Car(1L, "宝马", "BMW");
//将对象转换为Json格式字符串,json工具有fastjson,gson等
String redisValue = JSON.toJSONString(car);
//存入redis
stringRedisTemplate.opsForValue().set("car2", redisValue);
//取出redis
String car2Value = stringRedisTemplate.opsForValue().get("car2");
//将json字符串转换为对象
Car car2 = JSON.parseObject(car2Value, Car.class);
存入redis数据为json字符串
一般我们存取redis使用json格式的数据,为了存取方便,我们可以自定义序列化器来将数据自动使用json格式序列化。这里我使用fashjson工具提供的GenericFastJsonRedisSerializer来进行序列化
@Configuration
@EnableCaching
public class RedisConfig {
/**
* 重写Redis序列化方式,使用Json方式:
* RedisTemplate默认使用的是JdkSerializationRedisSerializer,
* 在此我们将自己配置RedisTemplate并定义使用fastjson提供的Serializer。
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置键(key)的序列化采用StringRedisSerializer。
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置值(Value)的序列化采用fastJson序列化
redisTemplate.setValueSerializer(new GenericFastJsonRedisSerializer());
return redisTemplate;
}
}
再次存取数据
@Test
void redisDemo1() {
Car car = new Car(1L, "宝马", "BMW");
//存放数据
redisTemplate.opsForValue().set("car1", car);
//取数据
Car car1 = (Car) redisTemplate.opsForValue().get("car1");
}
发现存入redis时自动将对象转为json
对于缓存声明,Spring 的缓存抽象提供了一组 Java 注解:
由于使用spring的缓存注解,其序列化器还是默认的,所以使用注解前,我们还需配置序列化器。
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
GenericFastJsonRedisSerializer genericFastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericFastJsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
@Cacheable
:声明方法返回值是可缓存的,即将结果存储在缓存中,以便在后续调用(具有相同参数)时返回缓存中的值,而无需实际执行该方法。
存储的键名支持SpEL表达式
Example | |||
---|---|---|---|
methodName |
Root object | 要调用的方法的名称 | #root.methodName |
method |
Root object | 正在调用的方法 | #root.method.name |
target |
Root object | 正在调用的目标对象 | #root.target |
targetClass |
Root object | 被调用的目标的类 | #root.targetClass |
args |
Root object | 用于调用目标的参数(作为数组) | #root.args[0] |
caches |
Root object | 执行当前方法的缓存的集合 | #root.caches[0].name |
Argument name | Evaluation context | 任何方法参数的名称。如果名称不可用(可能是由于没有调试信息),则参数名称在参数索引的位置下也可用(从 0开始) | #iban 或(您也可以使用或表示法作为别名)。#a0``#p0``#p<#arg> |
result |
Evaluation context | 方法调用的结果(要缓存的值)。仅在表达式、表达式(用于计算 ) 或表达式(当为 时)中可用。对于受支持的包装器(如 ),是指实际对象,而不是包装器。 | #result |
@CacheEvict
:用于声明方法正常执行,并在执行后清空指定key值的缓存或全部的缓存。
@CachePut
:用于声明方法正常执行,并在执行后更新缓存。
@Caching
:有时,需要指定同一类型的多个注释(如 或 ),例如,因为条件或键表达式在不同的缓存之间不同。 允许在同一方法上使用多个嵌套 、和注释。下面的示例使用两个注释:
@CacheConfig
:在类级别共享一些常见的缓存相关设置。
示例代码如下
@Service
//指定默认缓存区.缓存区:key的前缀,与指定的key构成redis的key,如 user::list
@CacheConfig(cacheNames = "user")
public class UserService {
@Autowired
private UserDao userDao;
//将方法返回结果放入指定key的缓存中,下次判断缓存中是否有对应key的数据,有则在缓存中读取,没有则执行方法
@Cacheable(key = "'list'")
public List<User> getUsers(){
System.out.println("执行查询方法》》》》》》》》》》》》》》》》》》》");
List<User> users = userDao.getUsers();
return users;
}
//删除指定key的缓存,对应增删改方法时使用
@CacheEvict(key = "'list'")
public void insertUser(){
User user = new User(100L, "张三", 20, new Date(), null);
userDao.saveUser(user);
}
}