消息服务的两个重要概念:
1.消息代理
2.目的地
目的地有两种:
a.队列:点对点消息通信:消息只有唯一的发送者和接受者,但不是只有一个接收者,也就是说发送者发送的消息可以被多个接收者接收,但信息被其中一个接收者接受后,其他接收者不可接受。
b.主题:发布/订阅消息通信:发送者将消息发送到主题,这个主题的所有订阅者会在消息到达时同时接收到消息。
当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定目的地。
消息规范:
1.JMS Java消息服务,不能跨平台、跨语言,实现:ActiveMQ、HornetMQ
2.AMQP 高级消息队列协议,实现:RabbitMQ
Spring支持:
1.spring-jms提供了对JMS的支持;spring-rabbit提供了对AMQP的支持
2.需要ConnectionFactory的实现来连接消息代理
3.提供JmsTemplate、RabbitTemplate来发送消息
4.@JmsListener、@RabbitListener注解在方法上监听消息代理发布的消息
5.@EnableJms、@EnableRabbit开启支持
6.JmsAutoConfiguration、RabbitAutoConfiguration自动配置
Exchange类型:
四种类型:direct、fanout、topic、header(header用的很少且性能差)。
direct:点对点通信,根据路由键匹配,完全符合bind规则才进行发送
fanout:广播
topic:可以对路由键进行模糊匹配,以单词为单位,单词之间用"."隔开。可使用的通配符为:符号#:匹配0个或多个单词;符号*:匹配一个单词
rabbitmq端口:5672 管理界面端口:15672
创建一个消息交换器和队列绑定:
1.首先创建exchange,type选择exchange的类型,durability选择可持续化,durable为持久化即重启rabbitmq仍保留
2.然后创建queue
3.点击创建的exchange进行绑定,填绑定的queue和路由键
Springboot使用rabbitmq:
1.依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.配置:
spring.rabbitmq.host=localhost
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#如果不配置端口和virtual——host,默认端口就是5672,默认virtual-host是"/"
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/
3.发送消息:
Message(消息头+消息体)需要自己构造序列化
rabbitTemplate.send(exchange,routekey,messsage);
不想构造Message(消息头+消息体),可以使用
rabbitTemplate.convertAndSend(exchange,routekey,object);
该方法自动序列化object,并发送
示例:
@Test
void sendTest01() {
Map<String,Object> map=new HashMap<>();
map.put("msg","这是第一个消息");
map.put("data", Arrays.asList("helloworld",123,true));
//发送消息
//对象被默认序列化后发送出去
//exchange.directtest为交换器的名称;test为路由键
rabbitTemplate.convertAndSend("exchange.directtest","test",map);
}
如果想用json串进行序列化的方式进行消息发送可添加配置类进行配置:
@Configuration
public class MyAMQPConfig {
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
示例:
@Test
void sendTest02() {
Map<String,Object> map=new HashMap<>();
map.put("msg","这是第二个消息");
map.put("data", Arrays.asList("fanout",123,true));
//发送消息
//fanout不需要写路由键
//对象被默认序列化后发送出去
rabbitTemplate.convertAndSend("exchange.fanout","",map);
}
跟direct一样,只是接收方根据路由键和绑定规则进行模糊匹配,示例:
@Test
void sendTest03() {
Map<String,Object> map=new HashMap<>();
map.put("msg","这是第三个消息");
map.put("data", Arrays.asList("topic",123,true));
//发送消息
//对象被默认序列化后发送出去
rabbitTemplate.convertAndSend("exchange.topic","test.news",map);
}
4.接收消息:
得到的是Message格式的数据(消息头+消息体)
rabbitTemplate.receive(queues);
得到的是对象(消息体转成的对象)
rabbitTemplate.receiveAndConvert(queues);
示例:
@Test
void receiveTest01() {
//接收消息,一个接收者接受数据后,队列中就没有了
//test为路由键
Object obj = rabbitTemplate.receiveAndConvert("test");
}
5.监听:
需要在启动项开启注释@EnableRabbit
然后配置server类
监听Object类型的信息的示例:
@Service
public class TestService {
@RabbitListener(queues = "test.news")
public void receive01(Map map){
System.out.println("收到消息"+map);
}
}
监听Message类型的信息的示例:
@Service
public class TestService {
@RabbitListener(queues = "test.news")
public void receive02(Message msg){
System.out.println(msg.getBody());
System.out.println(msg.getMessageProperties());
}
}
6.通过AmqpAdmin组件管理Queue、Exchange、Binding
创建Exchange示例:
@Test
public void createExchange(){
amqpAdmin.declareExchange(new DirectExchange("exchange.adqpadmin.direct"));
amqpAdmin.declareExchange(new FanoutExchange("exchange.adqpadmin.fanout"));
amqpAdmin.declareExchange(new TopicExchange("exchange.adqpadmin.topic"));
}
创建Queue示例:
@Test
public void createQueue(){
amqpAdmin.declareQueue(new Queue("amqp.queue",true));
}
创建Binding示例:
//new Binding(String destination, DestinationType type, String exchange, String routekey, Map<String,Object> arguments)
//destination是队列名
@Test
public void createBinding(){
amqpAdmin.declareBinding(new Binding("amqp.queue", Binding.DestinationType.QUEUE,"exchange.adqpadmin","amqp.test",null));
}
topic的Binding示例:
@Test
public void createBindingtopic(){
amqpAdmin.declareBinding(new Binding("amqp.queue", Binding.DestinationType.QUEUE,"exchange.adqpadmin.topic","amqp.*",null));
}
来源:CSDN
作者:是我弄得嘛
链接:https://blog.csdn.net/qq_38425719/article/details/104196038