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); }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。