SpringBoot+Redis realiza la publicación y suscripción de mensajes
1. Qué es redis publicar y suscribirse
Hay una línea en la introducción del documento en el sitio web oficial: Redis es un sistema de mensajería de publicación/suscripción rápido y estable.
2. Redis publicar y suscribirse
mecanismo
Redis proporciona funciones de publicación y suscripción, que se pueden utilizar para la transmisión de mensajes. El mecanismo de publicación y suscripción de Redis incluye tres partes, editor, suscriptor y canal (tema o cola).
3. Función de implementación de la línea de comandos
Suscríbete a temas
Redis utiliza un SUBSCRIBE channel
comando para suscribirse a un tema. El parámetro devuelto subscribe indica que el tema se ha suscrito correctamente. El segundo parámetro indica el nombre del tema de la suscripción y el tercero indica el número de suscripción actual.
127.0.0.1:6379> SUBSCRIBE ORDER-PAY-SUCCESS
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ORDER-PAY-SUCCESS"
3) (integer) 1
复制代码
Suscripción de coincidencia de patrones
La función de coincidencia de patrones permite a los clientes suscribirse a canales que coincidan con un patrón determinado. Redis utiliza un PSUBSCRIBE channel
comando para suscribirse a todos los canales que coinciden con un patrón determinado, con * para el patrón, y * puede reemplazarse por cualquier valor.
127.0.0.1:6379> PSUBSCRIBE ORDER-PAY-*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "ORDER-PAY-*"
3) (integer) 1
复制代码
Hacer un anuncio
Redis usa PUBLISH channel message
comandos para publicar mensajes sobre un tema, y el parámetro devuelto es la cantidad de suscriptores que recibieron el mensaje.
127.0.0.1:6379> PUBLISH ORDER-PAY-SUCCESS DD202109071525
(integer) 1
复制代码
darse de baja
Redis usa UNSUBSCRIBE channel
o PUNSUBSCRIBE channel
comandos para cancelar la suscripción de un tema. Dado que la operación de suscripción de Redis es de bloqueo, una vez que un cliente se suscribe a un canal o modo, permanecerá en el estado de suscripción hasta que salga. En los comandos , y SUBSCRIBE
, PSUBSCRIBE
el valor devuelto contiene el número de canales y modos actualmente suscritos por el cliente. Cuando este número se convierte en 0, el cliente saldrá automáticamente del estado de suscripción.UNSUBSCRIBE
PUNSUBSCRIBE
127.0.0.1:6379> UNSUBSCRIBE ORDER-PAY-SUCCESS
1) "unsubscribe"
2) "ORDER-PAY-SUCCESS"
3) (integer) 0
127.0.0.1:6379> PUNSUBSCRIBE ORDER-PAY-SUCCESS
1) "punsubscribe"
2) "ORDER-PAY-SUCCESS"
3) (integer) 0
复制代码
prueba
Primero, tres suscriptores se suscriben al tema ORDEN-PAGO-ÉXITO.Cuando el remitente envía el número de pedido en este tema, todos los suscriptores recibirán el mensaje de este tema.
4. Función de implementación de SpringBoot
Springboot integra Redis
importar paquete de dependencia
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.4.1</version>
</dependency>
</dependencies>
复制代码
Configurar archivo yaml
server:
port: 8888
spring:
application:
name: spring-boot-redis
redis:
host: 127.0.0.1
port: 6379
复制代码
Configurar la supervisión de mensajes
import com.demo.redis.listener.MessageListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
/**
* @author Bai
* @date 2021/4/29 上午 11:17
* @description
*/
@Configuration
public class RedisMessageConfig {
/**
* 监听订单支付完成主题
*/
private static final String ORDER_PAY_SUCCESS = "ORDER-PAY-SUCCESS";
/**
* 注入消息监听适配器
* @param messageListener
* @return {@link MessageListenerAdapter}
* @throws
* @author Bai
* @date 2021/9/7 下午 03:54
*/
@Bean
public MessageListenerAdapter getMessageListenerAdapter(MessageListener messageListener){
return new MessageListenerAdapter(messageListener, "onMessage");
}
/**
* 注入消息监听容器
* @param redisConnectionFactory
* @param messageListenerAdapter
* @return {@link RedisMessageListenerContainer}
* @throws
* @author Bai
* @date 2021/9/7 下午 03:54
*/
@Bean
public RedisMessageListenerContainer getRedisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory, MessageListenerAdapter messageListenerAdapter){
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
//订阅订单支付成功主题
redisMessageListenerContainer.addMessageListener(messageListenerAdapter, new PatternTopic(ORDER_PAY_SUCCESS));
return redisMessageListenerContainer;
}
/**
* 处理内容
* @param connectionFactory
* @return {@link StringRedisTemplate}
* @throws
* @author Bai
* @date 2021/9/7 下午 04:01
*/
@Bean
StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
}
复制代码
recibir mensaje
import org.springframework.stereotype.Component;
/**
* @author Bai
* @date 2021/9/7 下午 03:51
* @description
*/
@Component
public class MessageListener {
public void onMessage(String message){
System.out.println("接收消息:" + message);
}
}
复制代码
prueba
Enviar mensaje de éxito del pago del pedido
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
/**
* @author Bai
* @date 2021/9/7 下午 04:32
* @description
*/
@RunWith(value = SpringRunner.class)
@SpringBootTest
public class RedisPubTest {
/**
* 订单支付完成主题
*/
private static final String ORDER_PAY_SUCCESS = "ORDER-PAY-SUCCESS";
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 模拟发送5调订单支付完成的消息
* @throws
* @author Bai
* @date 2021/9/7 下午 04:57
*/
@Test
public void sendMessage(){
for (int i = 0; i < 5; i++) {
stringRedisTemplate.convertAndSend(ORDER_PAY_SUCCESS,"DD" + System.currentTimeMillis());
}
}
}
复制代码
Recibí el mensaje de que el pago del pedido fue exitoso
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.10.RELEASE)
2021-09-07 16:56:54.729 INFO 3712 --- [ main] com.demo.redis.RedisSubPubApplication : Starting RedisSubPubApplication on DESKTOP-595LI4G with PID 3712 (D:\Bai\Sources\spring-boot-demo\redis-sub-pub\target\classes started by 1 in D:\Bai\Sources\spring-boot-demo)
2021-09-07 16:56:54.735 INFO 3712 --- [ main] com.demo.redis.RedisSubPubApplication : No active profile set, falling back to default profiles: default
2021-09-07 16:56:55.205 INFO 3712 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2021-09-07 16:56:55.207 INFO 3712 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2021-09-07 16:56:55.229 INFO 3712 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 11 ms. Found 0 Redis repository interfaces.
2021-09-07 16:56:55.557 INFO 3712 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8888 (http)
2021-09-07 16:56:55.565 INFO 3712 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-09-07 16:56:55.565 INFO 3712 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.38]
2021-09-07 16:56:55.669 INFO 3712 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-09-07 16:56:55.669 INFO 3712 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 895 ms
2021-09-07 16:56:56.032 INFO 3712 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2021-09-07 16:56:56.950 INFO 3712 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8888 (http) with context path ''
2021-09-07 16:56:56.952 INFO 3712 --- [ main] com.demo.redis.RedisSubPubApplication : Started RedisSubPubApplication in 2.557 seconds (JVM running for 3.436)
接收消息:DD1631005025949
接收消息:DD1631005025964
接收消息:DD1631005025965
接收消息:DD1631005025967
接收消息:DD1631005025968
复制代码