SpringBoot2整合Redis快取
阿新 • • 發佈:2019-02-01
在學習springboot整合redis的時候遇到這樣一個奇怪的問題:我從資料庫中取得的物件已經放入了redis中,而且從redis的客服端也可以檢視到對應的key,開始的時候還是正常的,能正常的從快取中取得並返回我需要的類;但是過一段時間第二次訪問這個方法時(這時應該是到redis裡面取)丟擲了java.lang.ClassCastException異常,說你的com.test.PerSon類(假設你存入快取的是com.test.PerSon類),不能轉為com.test.PerSon類。
這個就比較奇怪了,最後在不知道怎麼回事的情況下把
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
模組去掉了就正常了。這個也......;
1、pom檔案加入
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.0.3.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 --> <!-- 要用redis連線池 必須有pool依賴--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.5.0</version> </dependency>
2、application.properties 加入redis相關配置
spring.redis.host=192.168.19.173 spring.redis.port=6379 spring.redis.timeout=60s # 資料庫連線超時時間,2.0 中該引數的型別為Duration,這裡在配置的時候需要指明單位 spring.redis.timeout=60s # 連線池配置,2.0中直接使用jedis或者lettuce配置連線池 # 最大活躍連線數,負數為不限制 spring.redis.lettuce.pool.max-active=500 # 等待可用連線的最大時間,負數為不限制 spring.redis.lettuce.pool.max-wait=-1ms # 最大空閒連線數 spring.redis.lettuce.pool.max-idle=100 # 最小空閒連線數 spring.redis.lettuce.pool.min-idle=20
3、啟動類加註解
@EnableCaching
4、快取配置類
package com.ps.uzkefu.common;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Author:ZhuShangJin
* Date:2018/6/25
*/
@Configuration
public class CacheConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
//使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
//使用StringRedisSerializer來序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
// redis快取和EhCache快取不能同時存在
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// RedisCacheManager cacheManager = RedisCacheManager.create(redisConnectionFactory);
// 生成一個預設配置,通過config物件即可對快取進行自定義配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config = config.entryTtl(Duration.ofMinutes(1)) // 設定快取的預設過期時間,也是使用Duration設定
.disableCachingNullValues(); // 不快取空值
// 設定一個初始化的快取空間set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("timeGroup");
cacheNames.add("user");
// 對每個快取空間應用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put("timeGroup", config);
configMap.put("user", config.entryTtl(Duration.ofSeconds(120)));
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory) // 使用自定義的快取配置初始化一個cacheManager
.initialCacheNames(cacheNames) // 注意這兩句的呼叫順序,一定要先呼叫該方法設定初始化的快取名,再初始化相關的配置
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
}
5、
Service層應用快取(註解方式)
@Service
public class PersonService {
@Autowired
private PersonRepo personRepo;
/**
* @Cacheable 應用到讀取資料的方法上,先從快取中讀取,如果沒有再從DB獲取資料,然後把資料新增到快取中
* unless 表示條件表示式成立的話不放入快取
* @param username
* @return
*/
@Cacheable(value = "user", key = "#root.targetClass + #username", unless = "#result eq null")
public Person getPersonByName(String username) {
Person person = personRepo.getPersonByName(username);
return person;
}
/**
* @CachePut 應用到寫資料的方法上,如新增/修改方法,呼叫方法時會自動把相應的資料放入快取
* @param person
* @return
*/
@CachePut(value = "user", key = "#root.targetClass + #result.username", unless = "#person eq null")
public Person savePerson(Person person) {
return personRepo.savePerson(person);
}
/**
* @CacheEvict 應用到刪除資料的方法上,呼叫方法時會從快取中刪除對應key的資料
* @param username
* @return
*/
@CacheEvict(value = "user", key = "#root.targetClass + #username", condition = "#result eq true")
public boolean removePersonByName(String username) {
return personRepo.removePersonByName(username) > 0;
}
public boolean isExistPersonName(Person person) {
return personRepo.existPersonName(person) > 0;
}
}