1.安装rabbitmq
//下载镜像,我下载的这个lastest镜像没有web功能,也就是15672端口没有反应
docker pull rabbitmq
//启动镜像,这里15672端口没办法用,使用的话下载其他镜像
docker run -d --hostname my-rabbit --name rabbit -e RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password -p 15672:15672 -p 5672:5672 rabbitmq
2.配置springboot
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
spring.rabbitmq.host=192.168.134.132
spring.rabbitmq.username=user
spring.rabbitmq.password=password
spring.rabbitmq.port=5672
3.进行简单的队列发送,路由发送,topic模式发送
(1)对指定队列进行发送和接收:
package com.example.demo.web;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
/**
* @Auther: gaoyang
* @Date: 2018/12/5 14:13
* @Description:
*/
@RestController
@Configuration
public class MyWeb {
@Autowired
RabbitTemplate rabbitTemplate;
//注册一个队列
@Bean
public Queue queue1() {
return new Queue("myQueue");
}
@GetMapping("/b")
public Object b(){
rabbitTemplate.convertAndSend("myQueue","测试");
return "ok";
}
}
(2)对指定路由发送数据
//第二个队列
@Bean
public Queue queue2() {
return new Queue("test222");
}
//注册一个交换机
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("fan");
}
//将两个队列绑定到该路由器
@Bean
public Binding binding3(){
return BindingBuilder.bind(queue2()).to(fanoutExchange());
}
@Bean
public Binding binding4(){
return BindingBuilder.bind(queue1()).to(fanoutExchange());
}
//第二个队列名称忽略,这样就会向两个队列同时发送信息
@GetMapping("/c")
public Object c(){
rabbitTemplate.convertAndSend("fan",null,"测试");
return "ok";
}
(3)topic动态交换机名称发送
//注册一个动态交换机
@Bean
public TopicExchange topicExchange() {
return new TopicExchange("jiaohuan");
}
//这里绑定队列后路由名称为topic.msg
@Bean
public Binding binding(@Qualifier("queue1") Queue queue1, TopicExchange topicExchange) {
return BindingBuilder.bind(queue1).to(topicExchange).with("topic.msg");
}
//这里的名字使用.#,#代表0到多个字符,*代表一个字符.所以这里会正则的匹配
@Bean
public Binding binding2(@Qualifier("queue2") Queue queue2, TopicExchange topicExchange) {
return BindingBuilder.bind(queue2).to(topicExchange).with("topic.#");
}
//所以这里发送的话,路由名称为topic.msg会像两个队列同时发送,如果为topic.aaa其他等则只会正则的匹配一个队列;
4.消费类
@Component
public class Consumer {
@RabbitListener(queues = "test111")
public void listen(List list){
System.out.println(list.get(0));
}
@RabbitListener(queues = "test222")
public void listen2(String list){
System.out.println(list);
}
}
4.ack模式
spring.rabbitmq.host=192.168.134.132
spring.rabbitmq.username=user
spring.rabbitmq.password=password
spring.rabbitmq.port=5672
# 开启发送确认
spring.rabbitmq.publisher-confirms=true
# 开启发送失败退回
spring.rabbitmq.publisher-returns=true
# 开启ACK
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.listener.simple.acknowledge-mode=manual
配置发送消息的异步结果:(该处可以做业务处理,重新发送等),此处是发送方到mq的结果
@Component
public class MyConfirm implements RabbitTemplate.ConfirmCallback {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (!ack) {
System.out.println("Confirm 消息发送失败" + cause + correlationData.toString());
} else {
System.out.println("Confirm 消息发送成功 ");
}
}
}
mq到接收方的结果:如果失败可以使用重新发送
@Component
public class MyCallBack implements RabbitTemplate.ReturnCallback {
@Autowired
RabbitTemplate rabbitTemplate;
@Override
public void returnedMessage(Message message, int i, String s, String s1, String s2) {
System.out.println("sender return " + message.toString()+"==="+i+"==="+s1+"==="+s2);
rabbitTemplate.send(message);
}
}
发送信息:
@GetMapping("/d")
public Object d() {
rabbitTemplate.setReturnCallback(myCallBack);
rabbitTemplate.setConfirmCallback(myConfirm);
rabbitTemplate.convertAndSend("test333", "测试");
return "ok";
}
消息接收者:
@RabbitListener(queues = "test333")
public void listen3(String list, Channel channel, Message message) throws IOException {
System.out.println(list);
try {
int a= 100/0;
//告诉服务器收到这条消息 已经被我消费了 可以在队列删掉 这样以后就不会再发了 否则消息服务器以为这条消息没处理掉 后续还会在发
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
System.out.println("receiver success");
} catch (Exception e) {
e.printStackTrace();
//丢弃这条消息
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
System.out.println("receiver fail");
}
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
以上第一个参数是该条数据的index标识,后面参数是是否全部处理小于当前index值得信息为接收成功;
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
以上第一个和第二个参数与上面同理,这里是是否全部置于接收失败,第三个参数为是否重新接收数据;
具体的方法含义可以参数这个---链接;