1. 程式人生 > 程式設計 >spring boot+redis 監聽過期Key的操作方法

spring boot+redis 監聽過期Key的操作方法

前言:

在訂單業務中,有時候需要對訂單設定有效期,有效期到了後如果還未支付,就需要修改訂單狀態。對於這種業務的實現,有多種不同的辦法,比如:

1、使用querytz,每次生成一個訂單,就建立一個定時任務,到期後執行業務程式碼;

2、rabbitMq中的延遲佇列;

3、對Redis的Key進行監控;

1、引入依賴

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

2、修改boot的redis配置

spring:
 #redis
 redis:
 database: 0
 host: 127.0.0.1
 password: redis_123456
 port: 6379

3、在伺服器中 修改redis.conf配置檔案(原來notify-keyspace-events 屬性是" " 空的,我們只需要填上“Ex”就行了)

notify-keyspace-events "Ex"

4、建立一個Redis監控類,用於監控過期的key,該類需繼承KeyExpirationEventMessageListener

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
 
import java.nio.charset.StandardCharsets;
 
/**
 * @program: SpringCloud
 * @description: redis Key過期監聽
 * @author: zhang yi
 * @create: 2020-03-24 14:14
 */
public class KeyExpiredListener extends KeyExpirationEventMessageListener {
 
 public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
  super(listenerContainer);
 }
 
 @Override
 public void onMessage(Message message,byte[] pattern) {
  System.out.println("過期key:" + message.toString());
 }
}

5、建立Redis配置類

import com.zy.rabbitmq.base.Listener.KeyExpiredListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
 
/**
 * @program: SpringCloud
 * @description: redis配置類
 * @author: zhang yi
 * @create: 2020-03-24 14:17
 */
@Configuration
public class RedisConfiguration {
 
 @Autowired
 private RedisConnectionFactory redisConnectionFactory;
 
 @Bean
 public RedisMessageListenerContainer redisMessageListenerContainer() {
  RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
  redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
  return redisMessageListenerContainer;
 }
 
 @Bean
 public KeyExpiredListener keyExpiredListener() {
  return new KeyExpiredListener(this.redisMessageListenerContainer());
 }
 
}

6、這裡提供一個redis工具類,用於儲存值,獲取值,獲取過期時間等操作。

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
 
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
/**
 * redis 工具類
 * @Author ZhangYi
 */
@Component
public class RedisUtil {
 
	@Resource
	private RedisTemplate<String,Object> redisTemplate;
 
	/**
	 * 指定快取失效時間
	 * 
	 * @param key 鍵
	 * @param time 時間(秒)
	 * @return
	 */
	public boolean expire(String key,long time) {
		try {
			if (time > 0) {
				redisTemplate.expire(key,time,TimeUnit.SECONDS);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
 
	/**
	 * 根據key 獲取過期時間
	 * 
	 * @param key 鍵 不能為null
	 * @return 時間(秒) 返回0代表為永久有效
	 */
	public long getExpire(String key) {
		return redisTemplate.getExpire(key,TimeUnit.SECONDS);
	}
 
	/**
	 * 判斷key是否存在
	 * 
	 * @param key 鍵
	 * @return true 存在 false不存在
	 */
	public boolean hasKey(String key) {
		try {
			return redisTemplate.hasKey(key);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
 
	/**
	 * 刪除快取
	 * 
	 * @param key 可以傳一個值 或多個
	 */
	@SuppressWarnings("unchecked")
	public void del(String... key) {
		if (key != null && key.length > 0) {
			if (key.length == 1) {
				redisTemplate.delete(key[0]);
			} else {
				redisTemplate.delete(CollectionUtils.arrayToList(key));
			}
		}
	}
 
	// ============================String=============================
	/**
	 * 普通快取獲取
	 * 
	 * @param key 鍵
	 * @return 值
	 */
	public Object get(String key) {
		return key == null ? null : redisTemplate.opsForValue().get(key);
	}
 
	/**
	 * 普通快取放入
	 * 
	 * @param key 鍵
	 * @param value 值
	 * @return true成功 false失敗
	 */
	public boolean set(String key,Object value) {
		try {
			redisTemplate.opsForValue().set(key,value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
 
	}
 
	/**
	 * 普通快取放入並設定時間
	 * 
	 * @param key 鍵
	 * @param value 值
	 * @param time 時間(秒) time要大於0 如果time小於等於0 將設定無限期
	 * @return true成功 false 失敗
	 */
	public boolean set(String key,Object value,long time) {
		try {
			if (time > 0) {
				redisTemplate.opsForValue().set(key,value,TimeUnit.SECONDS);
			} else {
				set(key,value);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
}

7、測試。(這裡開放兩個介面,一個set值,並設定過期時間為10秒,一個獲取值和過期時間,當到達過期時間,看是否回去到過期Key)

@GetMapping("/put")
 public String demo(){
  redisUtil.set("name","zhangyi",10);
  return "aaa";
 }
 
 @GetMapping("/get")
 public Map<String,Object> get(){
  Map<String,Object> m =new HashMap<>();
  m.put("time",redisUtil.getExpire("name"));
  m.put("val",redisUtil.get("name"));
  return m;
 }

spring boot+redis 監聽過期Key的操作方法

spring boot+redis 監聽過期Key的操作方法

成功獲取到了過期Key,這裡亂碼是因為boot整合的Redis存key或者value的時候,沒有配置字串序列化。沒有配置的話是預設使用jdk本身的序列化的。

到此這篇關於spring boot+redis 監聽過期Key的文章就介紹到這了,更多相關spring boot+redis 監聽過期Key內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!