开发背景
为了实现当经纪人A提交分佣后如果三天后其他经纪人没有确认分佣就自动确认分佣,如果经纪人A修改分佣后再次提交分佣,时间重置为三天
实现方式
第一步:引入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.0</version>
</dependency>
第二步: 配置发送过期事件的通知
在redis.config文件中设置 notify-keyspace-events Ex
第二步:创建一个jedis工具类
@Component
public class JedisUtil {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.password}")
private String password;
private JedisPool jedisPool;
@PostConstruct
public void init() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
jedisPool = new JedisPool(poolConfig, host, port, 2000, password);
}
public Jedis getJedis() {
return jedisPool.getResource();
}
@PreDestroy
public void close() {
if (jedisPool != null) {
jedisPool.close();
}
}
}
第三步:发布订阅
本地代码
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
//有密码就设置
jedis.auth("aaaaa");
CommissionInfoListener listener = new CommissionInfoListener();
String expirationSubscription = "__keyevent@0__:expired";
new Thread(() -> {
try {
jedis.psubscribe(listener, expirationSubscription);
} catch (Exception e) {
System.out.println("Subscribing failed." + e.getMessage());
}
}).start();
}
springBoot正式项目
@Component
@Slf4j
public class CommissionInfoLineRunner implements CommandLineRunner {
@Resource
private JedisUtil jedisUtil;
@Override
public void run(String... args) throws Exception {
log.info("订阅分佣三天自动确认开始~~~");
Jedis jedis = jedisUtil.getJedis();
CommissionInfoListener listener = new CommissionInfoListener();
String expirationSubscription = "__keyevent@0__:expired";
new Thread(() -> {
try {
jedis.psubscribe(listener, expirationSubscription);
} catch (Exception e) {
log.info("订阅失败,错误信息:{}", e.getMessage());
}
}).start();
}
}
代码解释
1.__keyevent@0__:expired含义
键空间通知会发送两种不同类型的事件消息:keyspace 和 keyevent
keyspace :键空间通知
keyevent :键事件通知
0:指的是库名称,一般默认为0
2. psubscribe
在使用 Jedis 的
psubscribe
方法时,遇到程序卡住不执行的情况是因为psubscribe
是一个阻塞操作,它会持续监听指定模式的消息直到被外部显式地取消订阅。这是 Redis 发布订阅模式的常见行为。它设计为一直运行,直到接收到取消订阅的命令。所以在本地运行main方法后要保持运行状态,不然订阅不到消息。springboot项目中可以实现CommandLineRunner实现
第四步:监听订阅消息
代码
@Service
@Slf4j
public class CommissionInfoListener extends JedisPubSub {
@Resource
CommissionInfoService commissionInfoService;
@Override
public void onPMessage(String pattern, String channel, String message) {
if (message.contains("aimeng:commissionInfo:confirmation:")) {
Long commissionInfoId = Long.parseLong(StrUtil.subAfter(message, ':', true));
log.info("分佣账单三天后自动确认开始,分佣id为:"+commissionInfoId);
// commissionInfoService.ok(CollUtil.newArrayList(commissionInfoId));
}
}
}
解释
1.参数message
参数message是当前监听到的key(键)
第五步:逻辑代码
jedisUtil.getJedis().setex(COMMISSIONINFO_CONFIRMATION_KEY + id, EXPIRETIME, "commissionInfo");