目錄
引言
Spring Boot支持的NoSQL數據庫有Redis、MongoDB,這篇文章我們來介紹Spring Boot整合Redis,以及利用Redis做緩存(注意:本人示例代碼基於Spring Boot 2.0.3,如果Spring Boot版本不相同的話,配置可能也不盡相同,還請各位博友注意自己Spring Boot的版本)。
本文示例代碼:https://github.com/lizitaowork/SpringBoot-demo.git
導入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Redis配置
創建Java類並繼承CachingConfigurerSuport,需要註冊類RedisConnectionFactory,代碼如下(類中的其它配置會在後面講到):
@Configuration //標註此類爲配置類
@EnableCaching //開啓緩存
public class RedisConfig extends CachingConfigurerSupport {
/**
*
* 自定義緩存key生成策略,若想使用這個key, 只需要將註解上keyGenerator值設置爲keyGenerator即可
* @return
*/
@Bean
public KeyGenerator keyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object taget, Method method, Object... params) {
StringBuffer sb = new StringBuffer();
sb.append(taget.getClass().getName());
sb.append(method.getName());
for(Object obj : params){
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* 構建連接工廠RedisCacheManager
* @return
*/
@Bean
public LettuceConnectionFactory lettuceConnectionFactory(){
return new LettuceConnectionFactory();
}
/**
* 構建緩存管理器RedisCacheManager
* @param lettuceConnectionFactory
* @return
*/
@Bean
public RedisCacheManager cacheManager(LettuceConnectionFactory lettuceConnectionFactory){
return RedisCacheManager.create(lettuceConnectionFactory);
}
/**
* 序列化RedisTemplate
* @param lettuceConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory){
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);
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(lettuceConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
}
在application.properties中配置連接Redis相關信息:
#redis數據庫索引,默認爲0
spring.redis.database=0
#redis服務器地址,默認爲localhost
spring.redis.host=localhost
#redis服務器連接端口,默認爲6379
spring.redis.port=6378
#redis服務器連接密碼,默認爲空
spring.redis.password=
#redis連接池最大阻塞等待時間,負值表示沒有限制(springBoot2.0開始,Redis 客戶端驅動現在由 Jedis變爲了 Lettuce)
spring.redis.lettuce.pool.max-wait=10ms
#redis連接池最大空閒連接
spring.redis.lettuce.pool.max-idle=8
#redis連接池中最小空閒連接
spring.redis.jedis.pool.min-idle=0
#redis連接池中最大連接數,負值表示沒有限制
spring.redis.lettuce.pool.max-active=8
#連接超時時間
spring.redis.timeout=1000ms
#設置spring緩存類型爲redis
spring.cache.type=redis
操作Redis
一、存取字符串
存取字符串很簡單,利用RedisTemplate的子類StringRedisTemplate來操作字符串類型,請看代碼:
@Service
public class StringRedisService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 保存數據到redis
* @param key
* @param value
* @return
*/
public String set(String key, String value){
stringRedisTemplate.opsForValue().set(key,value);
if(value.equals(stringRedisTemplate.opsForValue().get(key))){
return "set successful";
}
return "set failed";
}
/**
* 從redis獲取數據
* @param key
* @return
*/
@Cacheable(value = "cache", key = "#key")
public Object get(String key){
System.out.println("get方法執行了");
return stringRedisTemplate.opsForValue().get(key);
}
/**
* 刪除數據
* @param key
* @return
*/
public Object delete(String key){
return stringRedisTemplate.delete(key);
}
}
二、存取對象
存取對象,需要序列化RedisTemplate 和實體類,請看代碼:
/**
* 序列化RedisTemplate
* @param lettuceConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory){
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);
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(lettuceConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
//序列化Value爲Jackson2JsonRedisSerializer
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
實體類User代碼如下:
public class User implements Serializable {
private static final long serialVersionUID = -8499434066412998323L;
private String name;
private Integer age;
}
Service代碼如下:
@Service
public class UserService {
@Autowired
private RedisTemplate redisTemplate;
/**
* 保存User對象到redis中
* @param key
* @param user
* @return
*/
public String setUser(String key, User user){
boolean result = redisTemplate.opsForValue().setIfAbsent(key, user);
if(result){
return "set user successful";
}
return "set user failed";
}
/**
* 從redis中獲取User對象
* @param key
* @return
*/
public User getUser(String key){
System.out.println(key + "獲取數據!");
return (User)redisTemplate.opsForValue().get(key);
}
}
三、驗證
Controller代碼如下:
@RestController
@RequestMapping("/redis")
public class RedisController {
@Resource
private StringRedisService stringRedisService;
@Resource
private UserService userService;
@RequestMapping("/set")
public String set(){
return stringRedisService.set("testSet","hello world!");
}
@RequestMapping("/get/{key}")
public Object get(@PathVariable(value = "key") String key){
return stringRedisService.get(key);
}
@RequestMapping("/delete/{key}")
public Object delete(@PathVariable(value = "key") String key){
return stringRedisService.delete(key);
}
@RequestMapping(value = "/set/user", method = RequestMethod.POST)
public String setUser(@RequestBody RedisRequestVO<User> param) {
return userService.setUser(param.getKey(),param.getData());
}
@RequestMapping(value = "/get/user/{key}")
public User setUser(@PathVariable(value = "key") String key) {
return userService.getUser(key);
}
驗證結果如下:
緩存
一、配置
構建緩存管理器RedisCacheManager:
/**
* 構建緩存管理器RedisCacheManager
* @param lettuceConnectionFactory
* @return
*/
@Bean
public RedisCacheManager cacheManager(LettuceConnectionFactory lettuceConnectionFactory){
return RedisCacheManager.create(lettuceConnectionFactory);
}
自定義緩存key生成策略,若想使用這個key,只需要將註解上KeyGenerator值設置爲keyGenerator即可:
/**
* 自定義緩存key生成策略,若想使用這個key, 只需要將註解上keyGenerator值設置爲keyGenerator即可
* @return
*/
@Bean
public KeyGenerator keyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object taget, Method method, Object... params) {
StringBuffer sb = new StringBuffer();
sb.append(taget.getClass().getName());
sb.append(method.getName());
for(Object obj : params){
sb.append(obj.toString());
}
return sb.toString();
}
};
}
二、定義聲明式緩存
Spring提供了四個註解來定義緩存規則(基於AOP),如下表。
註解 | 解釋 |
---|---|
@Cacheable | 在方法執行前先查看緩存中是否有數據,如果有,則直接返回緩存數據;如果沒有,調用方法並將方法返回值放入緩存。 |
@CachePut | 無論怎麼,都將方法的返回值放入緩存中,一般用於更新數據的操作。 |
@CacheEvict | 將一條或多條數據從緩存中刪除。 |
@Caching | 組合多個註解策略在一個方法上。 |
代碼演示如下:
@Service
public class CacheService {
private Map<Integer, String> map = new HashMap<>();
@PostConstruct
public void init(){
map.put(1,"張三");
map.put(2,"李四");
}
/**
* 查找,如果沒有緩存,查詢並做緩存;
* 如果有緩存,直接拿緩存
* @param key
* @return
*/
@Cacheable(value = "generator", key = "'map_'+#key")
public String get(int key){
System.out.println(key + "獲取數據!");
return map.get(key);
}
/**
* 插入或更新數據
* 插入或更新成功,緩存到generator,如果緩存已存在則更新緩存
* @param key
* @param value
* @return
*/
@CachePut(value = "generator", key = "'map_'+#key")
public String put(int key, String value){
System.out.println(key + "更新數據爲:"+value);
map.put(key, value);
return map.get(key);
}
/**
* 刪除數據並刪除緩存
* @param key
* @return
*/
@CacheEvict(value = "generator", key = "'map_'+#key")
public String remove(int key){
System.out.println(key + "刪除數據");
map.remove(key);
return "remove success";
}
/**
* 自定義key
* @param key
* @return
*/
@Cacheable(value = "keyGenerator",keyGenerator = "keyGenerator")
public String cacheOfKeyGenerator(int key){
System.out.println(key + "獲取數據!");
return map.get(key);
}
}
三、開啓聲明式緩存
在使用聲明式緩存之前,需要開啓聲明式緩存,開啓聲明式緩存的方法非常簡單,只需要在配置類上加上@EnableCaching即可。
四、驗證
同樣的,我們用web方式來驗證,Controller代碼如下:
@RestController
@RequestMapping("/cache")
public class CacheController {
@Resource
private CacheService cacheService;
@RequestMapping("/get")
public String get(int key){
return cacheService.get(key);
}
@RequestMapping("/put")
public String put(int key, String value){
return cacheService.put(key, value);
}
@RequestMapping("/remove")
public String remove(int key){
return cacheService.remove(key);
}
@RequestMapping("/get/generator")
public String cacheOfKeyGenerator(int key){
return cacheService.cacheOfKeyGenerator(key);
}
}
驗證結果如下(僅演示@Cacheable效果,各位博友可自行驗證其他):