spring boot redis 监听过期Key spring boot+redis 监听过期Key的操作方法

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

spring boot redis 监听过期Key spring boot+redis 监听过期Key的操作方法

毅大师   2021-02-03 我要评论
想了解spring boot+redis 监听过期Key的操作方法的相关内容吗,毅大师在本文为您仔细讲解spring boot redis 监听过期Key的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点: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, time, 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;
 }

成功获取到了过期Key,这里乱码是因为boot集成的Redis存key或者value的时候,没有配置字符串序列化。没有配置的话是默认使用jdk本身的序列化的。

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们