(一)、添加依赖,SpringBoot中已经将Redis引入进来,直接添加redis模块
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(二)、配置Redis
redis:
host: 127.0.0.1
port: 6379
database: 0 //redis数据库索引序号,标识使用哪个数据库
password: //默认没有
jedis: //连接池
pool:
max-active: 8 //最大连接数(使用负值表示没有限制)
max-wait: -1ms //连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 8 //连接池种最大空闲连接数
min-idle: 0 //连接池种最小空闲连接数
timeout: 3000ms //连接超时时间毫秒
(三)、添加接口RedisService,用于定义一些常用的redis操作
/**
* redis操作Service,
* 对象和数组都以json形式进行存储
* Created by macro on 2018/8/7.
*/
public interface RedisService {
/**
* 存储数据
*/
void set(String key, String value);
/**
* 获取数据
*/
String get(String key);
/**
* 设置超期时间
*/
boolean expire(String key, long expire);
/**
* 删除数据
*/
void remove(String key);
/**
* 自增操作
* @param delta 自增步长
*/
Long increment(String key, long delta);
}
(四)、添加RedisService实现类RedisServiceImpl
/**
* redis操作Service的实现类
* Created by macro on 2018/8/7.
*/
@Service
public class RedisServiceImpl implements RedisService {
//注入RedisTemplate类,SpringBoot自动将其注入到了容器中了
@Autowired
private RedisTemplate stringRedisTemplate;
@Override
public void set(String key, String value) {
stringRedisTemplate.opsForValue().set(key, value);
}
@Override
public String get(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
@Override
public boolean expire(String key, long expire) {
return stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
@Override
public void remove(String key) {
stringRedisTemplate.delete(key);
}
@Override
public Long increment(String key, long delta) {
return stringRedisTemplate.opsForValue().increment(key,delta);
}
}
在SpringBoot中,如果没有自定义RedisTemplate的话,SpringBoot会自动往容器里注入一个默认的RedisTemplate,如果自定义了就使用的自定义的。
向redis缓存数据时会将数据进行序列化,
RedisTemplate默认使用JdkSerializationRedisSerializer进行序列化,即key, value需要实现Serializable接口。
StringRedisTemplate默认使用的是StringRedisSerializer序列化。这个bean的key,value都为String,所以要存储复杂数据时,要先将数据转换为String类型,一般转为json格式进行读取
(五)、自定义RedisTemplate
一般我们存取redis使用json格式的数据,为了存取方便,我们可以自定义序列化器来将数据自动使用json格式序列化。
可用fashjson工具提供的GenericFastJsonRedisSerializer来进行序列化
自定义并注入RedisTemplate
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;
}
}
(六)、使用声明式注解进行缓存
对于缓存的使用,Spring也提供了一组注解
其序列化是使用的默认的,所以在使用前需要进行配置
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;
}
//使用注解进行缓存,配置序列化方式
@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;
}
}
然后使用注解进行缓存
1.@Cacheable设置缓存,当缓存中没有这条key数据时就执行方法内容并进行缓存,下次调用方法就不会执行方法内容了,会自动在缓存中取数据
参数解释
cacheNames:缓存的名称
key :缓存中一条数据的key,可以自定义,也可以通过EL表达式用方法的参数。
//自定义key
@Cacheable(cacheNames = "product",key = "123")
public ProductInfo findById(String productInfoId) {
return repository.findById(productInfoId).get();
}
//用方法的参数作为key
@Cacheable(cacheNames = "product",key = "#productInfoId")
public ProductInfo findById(String productInfoId) {
return repository.findById(productInfoId).get();
}
//如果方法中参数为对象,还可用对象的属性
@Cacheable(cacheNames = "product",key = "#productInfo.productInfoId")
public ProductInfo findById(ProductInfo productInfo) {
return repository.findById(productInfo.getProductInfoId).get();
}
keyGenerator:定义key生成的类,但注意和属性key的不能同时存在,上面 的例子使用默认的keyGenerator,对应spring的SimpleKeyGenerator
//使用自定义key生成器
@Cacheable(cacheNames="book3", keyGenerator="myKeyGenerator")
public ProductInfo queryCacheableUseMyKeyGenerator(String id){
.........
return productInfo ;
}
//自定义key生成器,实现KeyGenerator接口,并实现generate方法
@Component
public class MyKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
.......
.......
return 123456;
}
}
sync:设置sync=true
1. 如果缓存中没有数据,多个线程同时访问这个方法,则只有一个方法会执行到方法,其它方法需要等待;
2. 如果缓存中已经有数据,则多个线程可以同时从缓存中获取数据
condition:判断条件,在所在方法调用前进行判断,如果为true就进行缓存,false就不缓存
unless :判断条件,在所在方法调用后进行判断,如果为true就不缓存,为false就进行缓存
condition和unless可同时使用
//判断条件condition实例
@Cacheable(cacheNames="book11",key="#id" condition="T(java.lang.Integer).parseInt(#id)<3")
public ProductInfo queryCacheableWithCondition(String id) {
.........
.........
return productInfo;
}
//判断条件unless 实例
@Cacheable(cacheNames="book11",key="#id" unless ="T(java.lang.Integer).parseInt(#id)<3")
public ProductInfo queryCacheableWithCondition(String id) {
.........
.........
return productInfo;
}
2.@CacheEvict,删除缓存数据
属性: allEntries ,默认为false,只删除key对应的数据;如果设置为true,则删除cacheNames=“product”中的所有数据
//删除缓存productInfo中的所有数据
@CacheEvict(cacheNames="productInfo", key="#id",allEntries=true)
public void updateBook(String id, String name){
productInfoService.updateById(id);
}
//删除缓存productInfo中key为id的那条数据
@CacheEvict(cacheNames="productInfo", key="#id")
public void updateBook(String id, String name){
productInfoService.updateById(id);
}
3.@CachePut,每次方法调用都会进行缓存替换,常用做更新数据操作。
//更新缓存中key为id的数据
@CachePut(cacheNames="productInfo", key="#id")
public ProductInfo queryUpdate(String id){
..........
return productInfo;
}
4.@CacheConfig,可以用此注解在类上定义并设置类全局属性cacheNames,则此类中的所有方法上 @Cacheable的cacheNames默认都是此值。当然@Cacheable也可以重定义cacheNames的值
@CacheConfig(cacheName="produvt")
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductInfoRepository repository;
@Override
@Cacheable(key = "123")
public ProductInfo findById(String productInfoId) {
return repository.findById(productInfoId).get();
}
//重定义cacheNames的值
@Override
@Cacheable(cacheNames = "product1111",key = "123")
public ProductInfo findById(String productInfoId) {
return repository.findById(productInfoId).get();
}
}