Redis拓展 - 实现定时消息通知

1. Redis实现定时消息通知

简单定时任务通知: 利用redis的keyspace notifications(即:键过期后事件通知机制)

  • 开启方法
    • 修改server.conf文件,找到notify-keyspace-events , 修改为“Ex”
    • 使用cli命令: redis-cli config set notify-keyspace-events Ex
  • redis 配置参考

2. 例子

创建springboot项目

  1. 修改pom.xml 和 yml
  • pom.xml


    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.6.9 
         
    
    cn.lazyfennec
    redisdemo
    0.0.1-SNAPSHOT
    redisdemo
    Demo project for Spring Boot
    
        1.8
    
    
        
            org.springframework.boot
            spring-boot-starter-data-redis
        

        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.projectlombok
            lombok
            true
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    


  • application.yml
spring:
  redis:
    database: 0
    host: 192.168.1.7
    port: 6379
    jedis:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 1
  1. 创建RedisConfig
package cn.lazyfennec.redisdemo.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @Author: Neco
 * @Description:
 * @Date: create in 2022/9/20 23:19
 */
@Configuration
@EnableCaching
public class RedisConfig {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 设置序列化
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置redisTemplate
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer); // key 序列化
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value 序列化
        redisTemplate.setHashKeySerializer(stringSerializer); // Hash key 序列化
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); // Hash value 序列化
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }  
}

  1. 创建RedisListenerConfiguration
package cn.lazyfennec.redisdemo.config;

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;

/**
 * @Author: Neco
 * @Description:
 * @Date: create in 2022/9/21 11:02
 */
@Configuration
public class RedisListenerConfiguration {

    @Autowired
    private RedisConnectionFactory factory;

    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer() {
        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
        redisMessageListenerContainer.setConnectionFactory(factory);
        return redisMessageListenerContainer;
    }
}
  1. 事件监听事件 RedisTask
package cn.lazyfennec.redisdemo.task;

import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

/**
 * @Author: Neco
 * @Description:
 * @Date: create in 2022/9/21 11:05
 */
@Component
public class RedisTask extends KeyExpirationEventMessageListener {

    public RedisTask(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 接收到事件后回调
        String channel = new String(message.getChannel(), StandardCharsets.UTF_8);

        String key = new String(message.getBody(), StandardCharsets.UTF_8);
        System.out.println("key:" + key + ", channel:" + channel);

    }
}
  1. 发布 RedisPublisher
package cn.lazyfennec.redisdemo.publisher;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Neco
 * @Description:
 * @Date: create in 2022/9/21 16:34
 */
@Component
public class RedisPublisher {

    @Autowired
    RedisTemplate redisTemplate;

    // 发布
    public void publish(String key) {
        redisTemplate.opsForValue().set(key, new Random().nextInt(200), 10, TimeUnit.SECONDS);
    }


    // 循环指定时间触发
    @Scheduled(cron = "0/15 * * * * ?")
    public void scheduledPublish() {
        System.out.println("scheduledPublish");
        redisTemplate.opsForValue().set("str1", new Random().nextInt(200), 10, TimeUnit.SECONDS);
    }

}
  1. 要实现Scheduled需要在启动类上加上注解
@SpringBootApplication
@EnableScheduling // 要加上这个,用以启动
public class RedisdemoApplication {
  1. 修改TestController
package cn.lazyfennec.redisdemo.controller;

import cn.lazyfennec.redisdemo.publisher.RedisPublisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: Neco
 * @Description:
 * @Date: create in 2022/9/21 16:32
 */
@RestController
public class TestController {

    @Autowired
    RedisPublisher redisPublisher;

    @GetMapping("/redis/{key}")
    public String publishEvent(@PathVariable String key) {
        // 发布事件
        redisPublisher.publish(key);
        return "OK";
    }
}

如果觉得有收获,欢迎点赞和评论,更多知识,请点击关注查看我的主页信息哦~

你可能感兴趣的:(Redis拓展 - 实现定时消息通知)