springboot中 玩转redis的发布订阅


一般我们使用redis最多的场景还是作为缓存中间件使用,redis也能做为消息队列使用,但这不是Redis的强项,不过如果需要的话还是可以使用的。

redis的发布订阅

集成到springboot中

  1. 引入redis starter
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
 </dependency>
  1. 新建一个RedisMessageListenerConfig

创建 RedisMessageListenerConfig之间要先自定义定义一个接口RedisPubSub接口,这个接口用于处理收到的信息,如果实现发布订阅只需实现这个接口即可。

public interface RedisPubSub {

    /**
     * 接收消息
     * @param message
     */
    void receiveMessage(String message);

    /**
     * 发布订阅监听的topic key
     * @return
     */
    CacheKeyEnum getCacheKeyEnum();
}
public enum CacheKeyEnum {

    /**
     * 消息订阅
     */
    PUBSUB_QUEUE("pubsub:queue"  , 0L),
    ;

    // 缓存键名
    private String key;
    
    /**
     * 过期时间,单位秒
     * 0 表示不过期
     */
    private Long expireTime;
    //省略getter、setter
}

RedisMessageListenerConfig.java

@Component
public class RedisMessageListenerConfig {
	// 如果项目中没有RedisPubSub实现类,启动会报错,所以设置required = false
    @Autowired(required = false)
    private Set<RedisPubSub> redisPubSubs;

    /**
     * 创建连接工厂
     * @return
     */
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory , Map<? extends MessageListener, Collection<? extends Topic>> listenerAdapters){
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);

        container.setMessageListeners(listenerAdapters);
        return container;
    }

    @Bean
    public Map<MessageListener, Collection<Topic>> listenerAdapters(){
        if (!CollectionUtils.isEmpty(redisPubSubs)) {
            Map<MessageListener, Collection<Topic>> map = new HashMap<>(redisPubSubs.size());
            for (RedisPubSub redisPubSub : redisPubSubs) {
                final CacheKeyEnum cacheKeyEnum = redisPubSub.getCacheKeyEnum();
                // redis会利用反射调用receiveMessage方法
                final MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(redisPubSub, "receiveMessage");
                messageListenerAdapter.afterPropertiesSet();
                map.put(messageListenerAdapter , Collections.singletonList(new PatternTopic(cacheKeyEnum.getKey())));
            }
            return map;
        }
        return Collections.emptyMap();
    }
}

准备redis工具类:

@Slf4j
@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
	/**
     * 消息发布
     * @param cacheKeyEnum
     * @param message
     */
    public void publish(CacheKeyEnum cacheKeyEnum , Object message){
        redisTemplate.convertAndSend(cacheKeyEnum.getKey() , message);
    }

    /**
     * 反序列化redis数据
     * @param value
     * @param <T>
     * @return
     */
    public <T> T deserialize(String value){
        final RedisSerializer<?> valueSerializer = redisTemplate.getValueSerializer();
        final Object deserialize = valueSerializer.deserialize(value.getBytes());
        return deserialize == null ? null : (T) deserialize;
    }
}

集成测试

  1. 实现RedisPubSub
@Component
public class PubsubQueue implements RedisPubSub {

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 接收消息
     *
     * @param message
     */
    @Override
    public void receiveMessage(String message) {
        System.out.println(message);
        final UserEntity deserialize = redisUtil.deserialize(message);
        System.out.println("getId="+deserialize.getId());

    }

    /**
     * 发布订阅监听的topic key
     *
     * @return
     */
    @Override
    public CacheKeyEnum getCacheKeyEnum() {
        return CacheKeyEnum.PUBSUB_QUEUE;
    }
}
  1. 单元测试
@Test
    public void testRedisQueue(){
        UserEntity userEntity = new UserEntity();
        userEntity.setId(123456L);
        redisUtil.publish(CacheKeyEnum.PUBSUB_QUEUE , userEntity);
    }

控制台输出:
在这里插入图片描述

使用redis发布订阅的注意点:
RedisPubSub 中receiveMessage接收的参数是String类型,redis在发布订阅中接收到的对象是字节数组,控制台打印是一个json格式的,如果redis用的是默认的JdkSerializationRedisSerializer序列化类,直接想通过将String转成JSON是不行的,会报错的,而且如果用的是jdk的序列化类,要发布的对象必须实现Serializable接口,否则也会报错。
所以可以通过上面的redisUtil中的反序列化方法来进行对象的转化,这样不管是不是用的是什么序列化类都不会报错。

Redis发布订阅的缺点:

消息不持久化,一旦订阅者没收到消息或者重启,消息将丢失。
相对于专业的消息中间件来说,Redis的发布订阅相对简单,慎用即可。

能力一般,水平有限,如有错误,请多指出。
如果对你有用点个关注给个赞呗

更多文章可以关注一下我的微信公众号suncodernote

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
Spring Boot使用Redis进行发布订阅可以通过以下步骤实现: 1. 配置Redis连接信息 在application.properties文件配置Redis连接信息,包括Redis的IP地址、端口号、密码等。 ``` spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= ``` 2. 配置RedisTemplate 在Spring Boot使用Redis需要使用到RedisTemplate,可以通过以下方式进行配置: ``` @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } } ``` 上述代码,我们配置了RedisTemplate的序列化方式,使用了StringRedisSerializer和GenericJackson2JsonRedisSerializer进行序列化。 3. 实现发布者 通过RedisTemplate实现发布者,可以使用convertAndSend方法进行消息发布。 ``` @Service public class RedisPublisher { @Autowired private RedisTemplate<String, Object> redisTemplate; public void publish(String channel, Object message) { redisTemplate.convertAndSend(channel, message); } } ``` 上述代码,通过@Autowired注入了RedisTemplate,并实现了publish方法,通过convertAndSend方法实现了消息的发布。 4. 实现订阅者 通过@RedisListener注解实现订阅者,可以监听Redis指定的频道,实现消息的订阅。 ``` @Service public class RedisSubscriber { @RedisListener(channel = "test") public void onMessage(Object message) { System.out.println("Received Message: " + message); } } ``` 上述代码,通过@RedisListener注解指定了监听的频道,实现了onMessage方法,当Redis有消息发布到该频道时,该方法会被回调。 5. 测试 在Spring Boot测试Redis发布订阅可以通过以下方式: ``` @RunWith(SpringRunner.class) @SpringBootTest public class RedisTest { @Autowired private RedisPublisher redisPublisher; @Test public void testPublish() { redisPublisher.publish("test", "Hello World!"); } } ``` 上述代码,通过@Autowired注入了RedisPublisher,实现了testPublish方法,调用publish方法发布了一条消息到test频道。 运行测试后,可以在RedisSubscriber的onMessage方法看到收到了发布的消息。 以上就是Spring Boot使用Redis进行发布订阅的详细步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

索码理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值