1.springboot整合Redis作缓存(10)
(1)当Redis当做数据库或者消息队列来操作时,一般使用RedisTemplate来操作
(2)当Redis作为缓存使用时,可以将它作为Spring Cache的实现,直接通过注解使用
2.引入依赖:
(1)在pom文件中添加依赖:
<!-- 配置测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 配置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>
</dependency>
3.创建配置文件application.properties
(1)配置redis数据源
spring.redis.host=127.0.0.1
spring.redis.port=6379
#根据需要
#spring.redis.password=root
# 连接超时时间(毫秒)
spring.redis.timeout=10000
# Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
spring.redis.database=0
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
(2)SpringBoot将会自动配置redis,注入相关bean
(3)就可以使用@CacheConfig,@Cacheable,@CachePut,@CacheEvict了
4.使用Cache注解时的问题
(1)缓存对象集合中,缓存是以key-value形式保存的
(2)当不指定缓存的key时,SpringBoot会使用SimpleKeyGenerator生成key
<1>它是使用方法参数组合生成的一个key
(3)SpringBoot会使用SimpleKeyGenerator生成key的缺点
<1>如果2个方法,参数是一样的,但执行逻辑不同
<2>那么将会导致执行第二个方法时命中第一个方法的缓存
(4)Spring同样提供了方案:继承CachingConfigurerSupport并重写keyGenerator()
<1>下面贴出代码:
@Configuration
@EnableCaching//启用缓存
public class RedisConfig extends CachingConfigurerSupport{
/*
*如果没有这个bean,则redis可视化工具中的中文内容都会以二进制存储,不易检查
*项目启动时此方法先被注册成bean被spring管理
*覆写替换系统默认redisTemplete
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认的jdkSerializeable序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置value的序列化规则和 key的序列化规则
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;}
/**
* 自定义生成key的规则
* @return
*/
@Override
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
//格式化缓存key字符串
StringBuilder sb = new StringBuilder();
//追加类名
sb.append(o.getClass().getName());
//追加方法名
sb.append(method.getName());
//遍历参数并且追加
for (Object obj : objects){sb.append(obj.toString());
}System.out.println("调用Redis缓存Key : " + sb.toString());return sb.toString(); }};}
/**
* 采用RedisCacheManager作为缓存管理器
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisTemplate) {
return RedisCacheManager
.builder(redisTemplate)
.transactionAware()
.build();}}
<2>缓存的key是包名+方法名+参数列表,这样就很难会冲突了
5.编写Redis操作工具类
(1)将RedisTemplate实例包装成一个工具类,便于对redis进行数据操作
(2)代码示例如下:
/**
* redis操作工具类. (基于RedisTemplate)
*/
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 读取缓存
* @param key
* @return
*/
public String get(final String key) {
return redisTemplate.opsForValue().get(key);}
/**
* 写入缓存
*/
public boolean set(final String key, String value) {
boolean result = false;
try {redisTemplate.opsForValue().set(key, value);
result = true;
} catch (Exception e) {e.printStackTrace();}return result;}
/**
* 更新缓存
*/
public boolean getAndSet(final String key, String value) {
boolean result = false;
try {redisTemplate.opsForValue().getAndSet(key, value);
result = true;
} catch (Exception e) {e.printStackTrace();}return result;}
/**
* 删除缓存
*/
public boolean delete(final String key) {
boolean result = false;
try {redisTemplate.delete(key);result = true;
} catch (Exception e) {e.printStackTrace();}return result;}}
6.测试类
(1)测试用例类来完成对redis的读写
(2)代码示例如下
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class RedisTest {
@Resource
private RedisUtils redisUtils;
/**
* 插入缓存数据
*/
@Test
public void set() {
redisUtils.set("redis_key", "redis_vale");}
/**
* 读取缓存数据
*/
@Test
public void get() {
String value = redisUtils.get("redis_key");
System.out.println(value);}}
7.控制层调用redis
@RestController
@RequestMapping("/redis")
public class RedisController {
// @Autowired
// 系统默认的StringRedisTemplete
// private StringRedisTemplate stringRedisTemplate;
@Resource
private RedisUtil redisUtil;
// 添加
@RequestMapping(value = "/add", method = RequestMethod.POST)
public void saveRedis() {
redisUtil.set("test-key2", "test-value");}
// 获取
@RequestMapping(value = "/get", method = RequestMethod.GET)
public String getRedis() {
return redisUtil.get("test-key2").toString();}}
8.springboot2.0集成Redis注意事项
(1)默认使用lettuce作为客户端
(2)在springboot2.0以下版本默认使用Jedis作为客户端
<1>Jedis自带连接池,不需要添加依赖
<2>lettuce没有连接池,如果想要使用连接池需要手动添加依赖并配置
<3>springboot集成redis缓存有注解方式,redisAPI方式等
3.1.注解方式简单
3.2.redisAPI方式灵活