1. 程式人生 > 程式設計 >SpringBoot Redis快取資料實現解析

SpringBoot Redis快取資料實現解析

這篇文章主要介紹了SpringBoot Redis快取資料實現解析,文中通過示例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

1.啟用對快取的支援

spring對快取的支援有兩種方式:

a.註解驅動的快取

b.XML宣告的快取

本文主要介紹純Java配置的快取,那麼必須在配置類上新增@EnableCaching,這樣的話就能啟動註解驅動的快取。

2.使用Redis快取

快取的條目不過是一個鍵值對(Key-Value),其中key描述了產生value的操作和引數,因此會很自然的想到Redis。

Redis可以用來為srping快取抽象機制快取條目,Spring-Data-Redis提供了RedisCacheManager,這是CacheManager的一個實現。RedisCacheManager會與Redis伺服器協作,通過RedisTemplate將快取條目儲存到Redis中。

為了使用RedisCacheManager,我們需要RedisTmeplate Bean配置以及RedisConnectionFactory實現類(JedisConnectionFactory Bean配置)。

3.配置將快取條目儲存在Redis伺服器的快取管理器。

前提需要在pom.xml引入

<!--redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

在application.properties中配置redis連線相關引數

#配置redis
#在RedisProperties.class有redis的預設配置,預設host為localhost,預設埠為6379
spring.redis.host=127.0.0.1
spring.redis.port=6379

配置快取管理器

package com.niugang;
import java.lang.reflect.Method;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonAutoDetect;


@Configuration
//沒有@EnableCaching這個註解的話,程式碼不會報錯,就是內容不會放入redis中

@EnableCaching 

public class RedisConfig {
/**
* 快取管理器,不管用什麼的快取,都必須有快取管理器
*/
@Bean
public CacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate());
/*
* 設定快取保留的時間,預設是永久儲存
*/
redisCacheManager.setDefaultExpiration(60);
return redisCacheManager;
}


@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.afterPropertiesSet();
return jedisConnectionFactory;

}

   /**
* redis預設物件序列化是通過jdk來序列化的,這裡面不用預設序列化方式,用JackJson進行序列化
* 
* 設定key的型別為String型別
* 
* @return
*/
@Bean
@SuppressWarnings({ "rawtypes","unchecked" })
public RedisTemplate<String,String> redisTemplate() {
RedisTemplate<String,String> redisTemplate = new RedisTemplate<String,String>();

redisTemplate.setConnectionFactory(jedisConnectionFactory());

     // 使用Jackson2JsonRedisSerialize 替換預設序列化
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.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;

}

 /**
   * 生產key的策略
   * @return
   */
@Bean 
  public KeyGenerator wiselyKeyGenerator(){ 
    return new KeyGenerator() { 
      @Override 
      public Object generate(Object target,Method method,Object... params) { 
        StringBuilder sb = new StringBuilder(); 
        sb.append(target.getClass().getName()); 
        sb.append(method.getName()); 
        for (Object obj : params) { 
          sb.append(obj.toString()); 
        } 
        
        return sb.toString(); 
      } 
    };
}
}

4.為方法添加註解以支援快取

spring的快取抽象在很大程度上是圍繞切面構建的,在sprng中啟用快取時,會建立一個切面,它觸發

一個或更多的spring的快取註解。

spring提供了四個註解來宣告快取規則

5.填充快取

@Cacheable和CachePut都可以填充快取,他們之間還是確有差異的。

@Cacheable和CachePut共同的屬性

6.自定義key

@Cacheable和CachePut都有一個名為key的屬性,這個屬效能夠替代預設的key,t它是通過SpEl(Spring El表示式)表示式計算得到的。具體到我們的業務場景 save(User user),我們需要將key設定儲存為User物件中的id,我們通過mysql資料庫自動生成id,此時引數中的User物件還沒有id.幸好有SpEl。

7.在UserService中新增如下方法。

/**
* 查詢全部
* 
* @Cacheable,先在快取中找,有則直接返回,不去呼叫方法,沒有則呼叫方法,將結果放入快取中
* 
* 
* 預設的key是基於方法引數來確定的,queryList()這個方法沒有引數,所以需要生成key的策略
*/
//@Cacheable(value="findAll",keyGenerator="wiselyKeyGenerator")
public List<User> queryList() {
return userDao.findAll();
}

   /**
* @Cachable會條件性的出發對方法的呼叫,這個取決於快取中是不是已經有所需要的值。對於
* 所註解的方法,@CachePut採用一種更為直接的流程。帶有@CachePut註解的方法始終都會呼叫,
* 而的返回值也會放入到快取中。
* @CachePut先將物件儲存到db中,返回的物件User中的id作為快取中的key
* result能夠得到返回的User
* @param user
*/
@CachePut(value="save",key="#result.id.toString()")
@Transactional
public User save(User user) {
log.info("新增物件");
return userDao.save(user);

}

  /**
* 函式功能:根據id查詢
* 
* 當get被呼叫時,快取切面會攔截呼叫並在快取中查詢之前以名findOne儲存的返回值。快取的key是
* 傳遞到get()方法的id引數,這個引數還必須是String型別。如果按照這個key能
* 夠找到值得話就返回找到的值,方法不會在被呼叫。如果沒有找到值的話,那就會呼叫這個方法
* 並將返回值放到快取之中。
* 
* 預設是以引數id的值作為快取中的key的
* 
* 沒有新增key="#id.toString()" 可能為報java.lang.Integer cannot be cast to java.lang.String
* 因為key的型別為String型別
*/
@Cacheable(value="findOne",key="#id.toString()")
public User get(Integer id) {
log.info("從資料查詢id為:{}的物件",id);
return userDao.findOne(id);

}

   /**
* 刪除 
* @CacheEvict移除條目,可以用在返回值為void的方法上,但是@Cacheable,@CachePut不能用在返回值為void的方法上
* 
* @param id
*/
@CacheEvict(value="save",key="#id.toString()")
@Transactional
public void delete(int id) {
log.info("從資料刪除id為:{}的物件",id);
userDao.delete(id);
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。