1. 程式人生 > >基於SpringBoot 2.X整合Redis

基於SpringBoot 2.X整合Redis

基於SpringBoot 2.X整合Redis

說明:本文旨在整理SpringBoot 2.X整合Redis基礎功能,如有問題請指出


  1. 在pom.xml檔案中引入Redis的依賴
       <!--  Redis -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-redis</artifactId>
       </dependency>
       <dependency>
           <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version>2.4.2</version>
       </dependency>
  1. 配置application.yml檔案
spring:
 redis:
   database: 0       # Redis資料庫索引(預設為0)
   host: 10.0.9.6    # Redis伺服器地址
   port: 6379        # Redis伺服器連線埠
   timeout: 10000ms  # Redis連線超時時間
   jedis:
     pool:
       max-active: 5000   # 連線池最大連線數(使用負值表示沒有限制)
       max-wait: 1000ms   # 連線池最大阻塞等待時間(使用負值表示沒有限制)
       max-idle: 5000     # 連線池中的最大空閒連線
       min-idle: 0        # 連線池中的最小空閒連線
  1. 配置RedisConfig

這裡的cacheManager是基於SpringBoot 2.X的配置

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
   private Logger logger = LoggerFactory.getLogger(this.getClass());

   @Bean
   public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
       RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1)); // 設定快取有效期一小時
       return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)).cacheDefaults(redisCacheConfiguration).build();
   }

   @Bean
   public RedisTemplate<Serializable, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
       RedisTemplate<Serializable, Object> template = new RedisTemplate<>();
       template.setConnectionFactory(connectionFactory);

       //使用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資料操作異常處理 這裡的處理:在日誌中打印出錯誤資訊,但是放行
    * 保證redis伺服器出現連線等問題的時候不影響程式的正常執行,使得能夠出問題時不用快取
    */
   @Bean
   @Override
   public CacheErrorHandler errorHandler() {
       CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
           @Override
           public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
               logger.error("redis異常:key=[{}]", key, e);
           }

           @Override
           public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
               logger.error("redis異常:key=[{}]", key, e);
           }

           @Override
           public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
               logger.error("redis異常:key=[{}]", key, e);
           }

           @Override
           public void handleCacheClearError(RuntimeException e, Cache cache) {
               logger.error("redis異常:", e);
           }
       };
       return cacheErrorHandler;
   }
}

  1. 編寫RedisApi

Redis常用工具類

@Component
public class RedisApi {

   @Autowired
   private RedisTemplate<Serializable, Object> redisTemplate;

   /***
    * 獲取所有的key
    */
   public Set<Serializable> getKeys(String pattern) {
       return redisTemplate.keys(pattern);
   }

   /**
    * 寫入快取
    *
    * @param key   鍵
    * @param value 值
    * @return 寫入是否成功
    */
   public boolean setCache(final String key, Object value) {
       boolean res = false;
       try {
           ValueOperations<Serializable, Object> opsForValue = redisTemplate.opsForValue();
           opsForValue.set(key, value);
           res = true;
       } catch (Exception e) {
           e.printStackTrace();
       }
       return res;
   }

   /**
    * 寫入快取設定失效時間
    *
    * @param key        鍵
    * @param vaule      值
    * @param expireTime 失效時間
    * @param timeType   失效時間型別
    * @return 是否寫入成功
    */
   public boolean setCache(final String key, Object vaule, Long expireTime, TimeUnit timeType) {
       boolean res = false;
       try {
           ValueOperations<Serializable, Object> opsForValue = redisTemplate.opsForValue();
           opsForValue.set(key, vaule);
           redisTemplate.expire(key, expireTime, timeType);
           res = true;
       } catch (Exception e) {
           e.printStackTrace();
       }
       return res;
   }


   /**
    * 讀取快取
    *
    * @param key
    * @return
    */
   public Object getCache(final String key) {
       ValueOperations<Serializable, Object> opsForValue = redisTemplate.opsForValue();
       return opsForValue.get(key);
   }

   /**
    * 刪除對應的值
    *
    * @param key
    */
   public void remove(final String key) {
       if (exists(key)) {
           redisTemplate.delete(key);
       }
   }

   /**
    * 批量刪除對應的value
    *
    * @param keys
    */
   public void remove(final String... keys) {
       for (String key : keys) {
           remove(key);
       }
   }


   /**
    * 判斷快取中是否對應的值
    *
    * @param key
    * @return
    */
   public boolean exists(final String key) {
       return redisTemplate.hasKey(key);
   }

   /**
    * 批量刪除keys
    *
    * @param pattern
    */
   public void removePattern(final String pattern) {
       Set<Serializable> keys = redisTemplate.keys(pattern);
       if (keys.size() > 0) {
           redisTemplate.delete(keys);
       }
   }


   /**
    * 雜湊 新增  注意:hmSet方法,
    * isForce :false 只有當值不存在時存入 有值是忽略
    * true 無論如何都存入
    *
    * @param key
    * @param hashKey
    * @param value
    * @return 原先舊值
    */
   public Object hmSet(String key, Object hashKey, Object value, boolean update) {
       Object obj = null;
       try {
           HashOperations<Serializable, Object, Object> opsForHash = redisTemplate.opsForHash();
           obj = opsForHash.get(key, hashKey);
           if (obj != null && update) {
               opsForHash.delete(key, hashKey);
           }
           opsForHash.putIfAbsent(key, hashKey, value);
       } catch (Exception e) {
           e.printStackTrace();
       }
       return obj;
   }

   /**
    * 獲取所有hashMap 鍵值
    */
   public Map<Object, Object> hmGetKeys(Serializable key) {
       return redisTemplate.opsForHash().entries(key);
   }

   /**
    * 刪除鍵下 對map鍵值
    */
   public long hmDelete(Serializable key, Object... mapKeys) {
       return redisTemplate.opsForHash().delete(key, mapKeys);
   }

   /**
    * 批量新增
    */
   public void hmSets(Serializable key, Map<String, Object> maps) {
       redisTemplate.opsForHash().putAll(key, maps);
   }

   /**
    * 雜湊 獲取資料
    *
    * @param key
    * @param hashKey
    * @return
    */
   public Object hmGet(String key, Object hashKey) {
       HashOperations<Serializable, Object, Object> hm = redisTemplate.opsForHash();
       return hm.get(key, hashKey);
   }

   /**
    * 列表新增
    *
    * @param key
    * @param value
    */
   public void lPush(String key, Object value) {
       ListOperations<Serializable, Object> lt = redisTemplate.opsForList();
       lt.rightPush(key, value);
   }

   /**
    * 列表獲取
    * 阻塞獲取 當這段時間類有值時,獲得該值,如果過了這段時間還沒有值 返回為null
    */
   public Object lPopInBlock(String key, long overtime, TimeUnit time) {
       ListOperations<Serializable, Object> lt = redisTemplate.opsForList();
       return lt.leftPop(key, overtime, time);
   }

   /**
    * 列表獲取    直接獲取列表值
    */
   public Object lPopNoBlock(String key) {
       ListOperations<Serializable, Object> lt = redisTemplate.opsForList();
       return lt.leftPop(key);
   }

   /**
    * 獲取列表
    *
    * @param key
    * @param begin
    * @param end
    * @return
    */
   public List<Object> lRange(String key, long begin, long end) {
       ListOperations<Serializable, Object> lt = redisTemplate.opsForList();
       return lt.range(key, begin, end);
   }

   /**
    * 集合新增
    *
    * @param key
    * @param value
    */
   public void addSetData(String key, Object value) {
       redisTemplate.opsForSet().add(key, value);
   }

   /**
    * 集合獲取
    *
    * @param key
    * @return
    */
   public Object getSetMembers(String key) {
       return redisTemplate.opsForSet().members(key);
   }

   /**
    * 有序集合新增
    *
    * @param key
    * @param value
    * @param score
    */
   public void addZSetData(String key, Object value, double score) {
       redisTemplate.opsForZSet().add(key, value, score);
   }

   /**
    * 有序集合獲取
    *
    * @param key
    * @param beginScore
    * @param endScore
    * @return
    */
   public Set<Object> getZSetRangeByScourc(String key, double beginScore, double endScore) {
       return redisTemplate.opsForZSet().rangeByScore(key, beginScore, endScore);
   }
}
  1. 編寫測試Controller
@RestController
public class UserController {

   @Autowired
   private RedisApi redisApi;
   
   @RequestMapping("/testCache")
   public String testCache() {
       String cache = "This have no one";
       if (redisApi.getCache("testCache") == null) {
           redisApi.setCache("testCache", "This is testCache");
       } else {
           cache = redisApi.getCache("testCache").toString();
       }
       return cache;
   }

}
  1. 啟動專案執行:
    第一次訪問:
    在這裡插入圖片描述
    第二次訪問:
    在這裡插入圖片描述