目录
1.需求背景
需求:在规定的时间段内,我们去进行考试,在时间一过,我们就需要去进行统计,有多少人考试及格。
在实际项目中,我们肯定会有部分需求是要求过了某一时间点,去执行一些特定的操作,而这些时间点都是不规律、不相同的,如果我们使用定时任务去做的话,实时性不高,而且使用定时任务可能会出现某些数据上的问题。
思路:在新建的时候,在redis保存一个以特定开头的key-value,过期时间是(规定的结束时间 - 新建时间);当他这个键值对过期的时候,就可以在监听类里面注入自己相应的service、mapper去操作自己相应的业务;
注意:如果我们要在监听类里面执行一些相应的操作,在执行的过程中,是没有用户认证、登录的,像博主的项目,采用的是spring cloud + mybatis plus,我们项目中mybatis plus的配置,在执行增删改查功能的时候,会默认带上当前登录用户信息和租户id这一个条件的,以至于执行可能会报错
2.创建监听类
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class KeyExpiredEventMessageListener implements MessageListener {
@Override
public void onMessage(Message message, byte[] bytes) {
log.info("监听失效的redisKey:{},值是:{}, {}", message.toString(), new String(message.getBody()), new String(bytes));
String expireKey = message.toString();
if (expireKey.startsWith(BusinessConstant.REDIS_KEY_PRE))) {
//执行特定的业务逻辑
}
}
}
3.创建配置类
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
@Configuration
public class RedisListenerConfig {
@Value("${spring.redis.database}")
private Integer db;
@Bean
public RedisMessageListenerContainer customizeRedisListenerContainer(
RedisConnectionFactory redisConnectionFactory,MessageListener messageListener) {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
redisMessageListenerContainer.addMessageListener(messageListener,new PatternTopic("__keyevent@"+db.intValue()+"__:expired"));
return redisMessageListenerContainer;
}
}