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

网友投稿 501 2022-11-27


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

前言:

在订单业务中,有时候需要对订单设置有效期,有效期到了后如果还未支付,就需要修改订单状态。对于这种业务的实现,有多种不同的办法,比如:

1、使用querytz,每次生成一个订单,就创建一个定时任务,到期后执行业务代码;

2、rabbitMq中的延迟队列;

3、对Redis的Key进行监控;

1、引入依赖

org.springframework.boot

spring-boot-starter-data-redis

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.StandardCharshttp://ets;

/**

* @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 RedisConnegXCbUUctionFactory 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 redisTemplate;

/**

* 指定缓存失效时间

*

* @param key 键

* @param time 时间(秒)

* @return

*/

public boolean expire(String key, long time) {

try {

if (time > 0) {

rgXCbUUedisTemplate.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 get(){

Map m =new HashMap<>();

m.put("time",redisUtil.getExpire("name"));

m.put("val",redisUtil.get("name"));

return m;

}

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java调用微信支付功能的方法示例代码
下一篇:Intellij IDEA导入JAVA项目并启动(图文教程)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~