Redis implements the specific implementation of publish and subscribe functions

1: Tell me about the scene used at that time

Because the server needs to call the client, http requests cannot be used here, because the client's PC does not have a fixed IP address, just like a mobile phone. If you need to push messages, task scheduling must be done. But when doing task scheduling, the problem of continuously pushing messages in a loop is:

1: A continuous loop is required. If you only need to push a few times a day, it may be called thousands of times.

2: The loop must have a time interval and cannot be triggered in real time.

Due to the above two problems, I have learned about the long link mechanism of netty and the sending mechanism of the mqtt framework. Because they are too complicated and difficult to integrate into the project, I chose to use the publish and subscribe mechanism of redis.

Publish and subscribe features:

1: Push only when there is news, no need for different loop retrieval.

2: Trigger message push in real time, no need to wait, time delay

3: Channels can be used to achieve point-to-point push, that is, it can be fixed to a specific client or a certain type of client.

This solves the problem of the server triggering client events. In layman's terms, the server can trigger the client's method implementation interface as needed. Of course, the client method cannot be understood as an API here, and it cannot be called directly.

As shown in the figure, there is no direct relationship between the server (the publisher can also understand the client of the redis service) and the client (subscriber).

 2: Directly use the redis console to implement publish and subscribe

1: Find redis-cli.exe in the installed redis path

 2: Double-click to open a client link: enter the key above: subscribe

Subscribersubscribe test1

    SUBSCRIBE channel [channel ...]

 Subscribe to a given channel or channels.

test1 is a channel, that is, the publisher must publish to this channel so that the subscriber can receive the message. Otherwise, the message will not be received.

 Publisher: publish test1 message

When a message is published on the publisher, the subscriber can immediately receive a message with related content.

    PUBLISH channel message

  Send information message to the specified channel channel.

Three: Integrating the redis publish and subscribe function under the java-spring boot framework

For the specific process of integrating redis with spring boot, please refer to:

What the hell, the interviewer actually asked me to use Redis to implement a message queue! ! ? - Jianshu

Here is the implementation of the publish and subscribe function based on this document

1: Continue to add methods based on the original RedisConfig configuration. All copies are as follows:

Things to note here:

container.addMessageListener(listenerAdapter, new PatternTopic("test1"));This is the listening channel,

test1 is the name of the channel, which means that all messages from this channel can be monitored.

The addMessageListener method here can listen to multiple channels, which can be a list

subscriber:

@Configuration
    public class RedisConfig {
     
        @Bean
        public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
            RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(factory);
            GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
            // 值采用json序列化
            redisTemplate.setValueSerializer(serializer);
            //使用StringRedisSerializer来序列化和反序列化redis的key值
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            // 设置hash key 和value序列化模式
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashValueSerializer(serializer);
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }
     
        @Bean
        public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
                                                       MessageListenerAdapter listenerAdapter) {
            RedisMessageListenerContainer container = new RedisMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
     
            Collection<Topic> lists = new ArrayList();
            Topic list1= new PatternTopic("test1");
            Topic list2= new PatternTopic("test2");
            Topic list3= new PatternTopic("test3");
     
            lists.add(list1);
            lists.add(list2);
            lists.add(list3);
            container.addMessageListener(listenerAdapter,lists);
            //container.addMessageListener(listenerAdapter, new PatternTopic("test1"));
            return container;
        }
     
        /**
         * 绑定消息监听者和接收监听的方法,必须要注入这个监听器,不然会报错
         */
        @Bean
        public MessageListenerAdapter listenerAdapter() {
            return new MessageListenerAdapter(new Receiver(), "receiveMessage");
        }
     
    }

2: One of the classes in the above configuration is a custom class: Receiver

Add a class in the controller: Receiver,

package com.unit.mapping.controller;
     
    public class Receiver {
        public void receiveMessage(String message) {
            System.out.println(message);
        }
    }

3: Publisher: This can be implemented in any other project:

Use redisTemplate.converAndSend("channel", "send message"); If you send it like this, the above project can receive it.

For example: after my service is called by a certain front end, I need to distribute this message, but to whom? This depends on the channel. I just need to add this code below. Just add the messages that need to be distributed to the template.

 package com.unit.mapping.controller;
     
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.test.context.junit4.SpringRunner;
     
    import javax.annotation.Resource;
     
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class TestPack {
        @Resource
        private RedisTemplate redisTemplate;
        @Test
        public void test(){
            for (int i = 0; i < 10; i++) {
                System.out.println(i);
                redisTemplate.convertAndSend("test1","这是我发送的第"+i+"个消息");
            }
        }
    }

Guess you like

Origin blog.csdn.net/qq_16504067/article/details/131675614