SpringBoot整合Jedis实现监听键过期通知和消息订阅

开局的一些废话

在学习Redis命令手册的时候,订阅键过期的命令使用的时SUBSCRIBE命令。这个命令可以收到键的过期通知,但是无法接收到匹配模式的订阅消息,如果我要是既想要接收到键的过期通知,也想要接收到推送的消息,应该怎么办呢?用PSUBSCRIBE命令就可以做到。另外一个问题就是,在网上的一些文章中,大部分使用的都是SpringBoot自带的Redis工具,在Application.properties文件中配置Redis客户端的一些连接信息即可,但是如果我要是想用自己的客户端,应该怎么办?这篇文章包含以下内容:

  1. SpringBoot项目整合Jedis客户端
  2. @Autowired在非Controller中注入位空的问题
  3. Jedis订阅键过期通知和消息推送

创建项目

创建一个普通的springBoot项目即可,这部分就省略了。

添加相关的依赖

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <!--<artifactId>spring-boot-starter-redis</artifactId>-->
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!--连接池依赖-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>

创建Redis配置文件

在SpringBoot的目录中,创建一个redis.properties文件,这个文件中主要是配以一些Redis的链接相关的信息,内容如下:

#redis配置开始
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=zxc123456
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=1024
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=10000
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=200
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=10
# 连接超时时间(毫秒)
spring.redis.timeout=10000
spring.redis.block-when-exhausted=true

创建Redis配置类,读取配置信息

既然已经创建了redis的配置文件,那么我们肯定需要创建一个redis的配置类,来使用这些配置信息,这里的配置类我就叫做RedisConfig.java,以下是这个类的代码

@Configuration
@PropertySource("classpath:redis.properties")
@Slf4j
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;
    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWaitMillis;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.block-when-exhausted}")
    private boolean blockWhenExhausted;
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;
    @Bean
    public JedisPool reidsPoolFactory(){
       log.info("JedisPool注入成功!!");
       log.info("redis地址:"+host+":"+port);
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig() ;
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
        jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
        // 是否启用pool的jmx管理功能, 默认true
        jedisPoolConfig.setJmxEnabled(true);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout);
        jedisPool.getResource();
        return jedisPool;
    }

解决@Autowired注入为空

我们既然已经整合了Jedis,那么我们肯定是希望可以使用Jedis来订阅消息的,但是SpringBoot如果我们在一个普通的配置类里面使用@AutoWired注解注入对象的时候,注入的是一个null,那这个问题应该怎么解决呢?这里就直接把代码复制过来了,这里主要是通过@PostConstruct注解来解决的这个问题,在CSDN上同样有很多关于这个注解的说明,可以自行去查看,这里就不在过多的说明。如果我们想要获取一个Jedis的话,只需要调用这个getjedis的静态方法就可以了

@Component
public class JedisPoolAutowried {
    @Autowired
    private JedisPool jedisPool;
    private static JedisPoolAutowried redisKeyExpiredSubscriberRunnable;
    //这个时为了解决Autowired在非controller注入位空的问题
    @PostConstruct
    public void init(){
        redisKeyExpiredSubscriberRunnable = this;
        redisKeyExpiredSubscriberRunnable.jedisPool = this.jedisPool;
    }
    public static Jedis getjedis(){
        return redisKeyExpiredSubscriberRunnable.jedisPool.getResource();
    }
}

监听消息通知

编写消息处理类

这个消息处理类需要继承JedisPubSub 这个类,在并且需要实现onPMessage这个方法,因为我们通过PSUBSCRIBE命令订阅的消息,收到的消息类型是PMESSAGE,会触发这个方法。这个类里面还有其他的一些方法,可以自行去查看。

public class RedisPsubscribeListener extends JedisPubSub {
    @Override
    public void onPMessage(String pattern, String channel, String message) {
        System.out.println("Redis订阅监听超时通知开始pattern{"+pattern+" } channel{ "+channel+"} message{"+message+"}");
        if (StringUtils.isBlank(message)){
            System.out.println("Message消息为空");
            return;
        }
        System.out.println("Redis订阅监听超时通知完成 pattern{"+pattern+" } channel{ "+channel+"} message{"+message+"}");
    }
}

订阅消息

我们编写完消息处理类以后,需要让Jedis客户端来订阅这一些消息,代码如下:
这个类是一个线程,它实现了Runnable接口,需要注意的是,clientPsubscribe.psubscribe()是一个阻塞方法,它里面是通过do while循环来检测时间的,所以那个clientPsubscribe.close();方法一直后不会被执行,这里需要注意一下。并且psubscribe命令是支持匹配模式的,在下面的代码中,一共订阅了三种消息,第一个就是匹配模式,设置的是"news.* ",这代表以news.开头的消息,都可以检测到。例如:news.music,第二个是键过期通知,第三个就是一个普通的消息。
需要注意的一点是,如果想要收到键过期的通知,这里需要把Redis配置文件中的
notify-keyspace-events参数的值设置为Ex,或者是通过config set notify-keyspace-events Ex命令来设置。

public class RedisKeyExpiredSubscriberRunnable implements Runnable{

    @Override
    public void run() {
     	//这里使用的就是上面的Getjedis方法,可以从连接池中获取一个客户端,如果上面的JedisPoolAutowried 类中
        //不使用@PostConstruct注解,那么在这里只会获取到一个null值
        Jedis clientPsubscribe =JedisPoolAutowried.getjedis();
        RedisPsubscribeListener redisPsubscribeListener = new RedisPsubscribeListener();
        System.out.println("开始订阅过期事件");
        clientPsubscribe.psubscribe(redisPsubscribeListener,"news.*","__keyevent@0__:expired","redismessage");
        clientPsubscribe.close();
    }
}

Springboot加载

在我们编写完了消息订阅和消息的处理的相关的方法后,剩下的就是让SpringBoot来加载我这些配置,我们需要再创建一个类,这个类是给SpringBoot来使用的。这个类实现了CommandLineRunner 接口,在SprigBoot启动的过程中,会自动的加载这个方法,通常可以使用这个接口用来在SpringBoot启动的时候加载一些数据。如果有多个需要加载,可以通过@Order(value = 1)//启动顺序来设置加载顺序。

@Component
@Order(value = 1)//启动顺序
public class RedisPublisherRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        //用于启动后执行,一般是初始化的时候使用
        new Thread(new RedisKeyExpiredSubscriberRunnable()).start();
    }
}

启动SpringBoot,推送消息

启动SpringBoot

启动SpringBoot后,控制台会输出一条信息,这条信息是通过println语句来输出的,上面的代码中应该可以看到这一行代码
这条信息是通过pringln语句来输出的

推送消息

我们单独启动一个redis客户端,来输入一些消息,看看是否能够监听到

  1. 输入setex命令,设置一个具有过期时间的值
    在这里插入图片描述
    控制台输出的内容:
    在这里插入图片描述

  2. 输入PUBLISH news.nusic,通过匹配模式来推送消息:
    在这里插入图片描述

    控制台输出的消息
    在这里插入图片描述

  3. 推送一条普通的消息到redismessage频道下
    在这里插入图片描述
    控制台中显示的消息:
    在这里插入图片描述

结束

到此,我们已经实现了一个简单的SpringBoot整合Jedis实现监听键过期通知和消息订阅的demo,这是本人第一个写文章,里面可能有一些描述不准确的地方,欢迎指正。另外,关于notify-keyspace-events参数更详细的配置,可以去redis命令手册中查看

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中,可以通过整合Jedis来使用Redis作为缓存或者消息队列。下面是整合Jedis的步骤: 1. 添加依赖:在`pom.xml`文件中添加Jedis的依赖。可以使用以下依赖配置: ```xml <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.6.0</version> </dependency> ``` 2. 配置Redis连接信息:在`application.properties`文件中配置Redis的连接信息,包括主机、端口、密码等。例如: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= ``` 3. 创建Jedis连接池:在Spring Boot的配置类中创建Jedis连接池的Bean。可以使用以下代码示例: ```java import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; @Configuration public class RedisConfig { @Value("${spring.redis.host}") private String redisHost; @Value("${spring.redis.port}") private int redisPort; @Value("${spring.redis.password}") private String redisPassword; @Bean public JedisPool jedisPool() { JedisPoolConfig poolConfig = new JedisPoolConfig(); return new JedisPool(poolConfig, redisHost, redisPort, redisPassword); } } ``` 4. 使用Jedis进行操作:在需要使用Redis的地方,通过注入JedisPool对象并调用相应的方法来进行操作。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; @Service public class RedisService { @Autowired private JedisPool jedisPool; public void set(String key, String value) { try (Jedis jedis = jedisPool.getResource()) { jedis.set(key, value); } } public String get(String key) { try (Jedis jedis = jedisPool.getResource()) { return jedis.get(key); } } } ``` 以上就是Spring Boot整合Jedis的基本步骤。通过配置Redis连接信息和使用JedisPool对象,可以方便地在Spring Boot项目中使用Redis
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值