1. 生产者
  2. 创建一个SpringBoot项目springboot-producer,作为RabbitMQ的生产者。
  3. 在pom文件中引入相关的依赖坐标
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. 在配置文件中加入RabbitMQ的相关配置项
spring.rabbitmq.host=127.0.01
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#虚拟机
spring.rabbitmq.virtual-host=/test
#连接超时时间
spring.rabbitmq.connection-timeout=1000ms

#producer
#confirmslistener 消息是否投递成功
spring.rabbitmq.publisher-confirms=true
#没有队列接收消息时,返回一个状态
spring.rabbitmq.publisher-returns=true
#true当消息无法被正常送达的时候被返回给生产者,false丢弃
spring.rabbitmq.template.mandatory=true
  1. 创建一个需要发送消息的实体类(必须实现Serializable接口)
package com.kangswx.rabbitmq.springboot.domain;

import java.io.Serializable;

public class Employee implements Serializable {

    private String empno;
    private String name;
    private Integer age;

    public Employee() {
    }

    public Employee(String empno, String name, Integer age) {
        this.empno = empno;
        this.name = name;
        this.age = age;
    }

    public String getEmpno() {
        return empno;
    }

    public void setEmpno(String empno) {
        this.empno = empno;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
  1. 创建一个发送消息的类,在类上面需要添加@Component注解。在没有启动消费者之前,如果没有创建对应的交换机,则会投递消息失败,此时需要手动创建交换机。
import com.kangswx.rabbitmq.springboot.domain.Employee;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MessageProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //创建一个消息是否投递成功的监听对象confirmCallback
    RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
        // 第一个参数, 消息的附加消息(自定义id),
        // 第二个参数, 消息是否被Broker接收,isAck(true接收,false拒收),
        // 第三个参数, 如果拒收,则返回拒收的原因
        @Override
        public void confirm(CorrelationData correlationData, boolean isAck, String s) {
            System.out.println("======》correlationData: " + correlationData);
            System.out.println("======》isAck: " + isAck);
            if(!isAck){
                System.err.println("======》s: "+s);
            }
        }
    };

    //创建一个处理消息是否被队列接收的监听对象,如果没有队列接收发出的消息,则会自动调用returnedMessage方法,进行后续的处理
    RabbitTemplate.ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {

        // 第一个参数, 被退回的消息
        // 第二个参数, 错误编码
        // 第三个参数, 错误描述
        // 第四个参数, 交换机的名字
        // 第五个参数, 路由Key
        @Override
        public void returnedMessage(Message message, int replyCode, String replyText, String exchangeName, String routingKey) {
            System.err.println("-----returnedMessage++code: " + replyCode +",  Text: " + replyText);
            System.err.println("-----returnedMessage++exchangeName: " + exchangeName +",  routingKey: " + routingKey);
            System.err.println("-----returnedMessage++message: " + message);
        }
    };

    public void sendMessage(Employee employee){
        //CorrelationData作用是作为消息的附加消息传递,通常我们用它来保存消息的自定义id
        CorrelationData correlationData = new CorrelationData(employee.getEmpno()+"-"+new Date().getTime());

        //设置消息是否投递成功的监听对象
        rabbitTemplate.setConfirmCallback(confirmCallback);

        //设置消息是否被队列成功接收的监听对象
        rabbitTemplate.setReturnCallback(returnCallback);

        //如果没有创建交换机的话,在投递消息的时候会投递失败
        //第一个参数,交换机的名称
        //第二个参数,路由key值
        //第三个参数,消息主题对应的类
        //第四个参数,消息的附件消息
        rabbitTemplate.convertAndSend("springboot-exchange", "hr.employee", employee, correlationData);
    }

}
  1. 消费者
  2. 创建一个SpringBoot项目springboot-consumer作为消息队列的消费者
  3. 在pom文件中引入相关的依赖坐标
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. 在application.properties中添加RabbitMQ的相关配置项
spring.rabbitmq.host=127.0.01
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#虚拟机
spring.rabbitmq.virtual-host=/test
#连接超时时间
spring.rabbitmq.connection-timeout=1000ms

#consumer
#简单配置,手动的
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#最小的消费者数量
spring.rabbitmq.listener.simple.concurrency=1
#最大的消费者数量
spring.rabbitmq.listener.simple.max-concurrency=5
  1. 创建一个需要发送消息的实体类(该类的包名和类名必须与生产者一致 且 必须实现Serializable接口)
import java.io.Serializable;

public class Employee implements Serializable {

    private String empno;
    private String name;
    private Integer age;

    public Employee() {
    }

    public Employee(String empno, String name, Integer age) {
        this.empno = empno;
        this.name = name;
        this.age = age;
    }

    public String getEmpno() {
        return empno;
    }

    public void setEmpno(String empno) {
        this.empno = empno;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
  1. 创建一个发送消息的类,在类上面需要添加@Component注解。在消费者中主要通过注解的方式完成相关的功能实现。当队列或交换机不存在的时候,会自动创建相关的队列或交换机,并进行绑定。消费者会一直处于等待状态,当有新的消息进来的时候,就会自动触发消费者的相关方法来处理消息。
package com.kangswx.rabbitmq.springboot;

import com.kangswx.rabbitmq.springboot.domain.Employee;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

@Component
public class MessageConsumer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 用于接收消息的方法
     * RabbitListener用于声明定义消息接收的队列与exchange绑定的信息,使消费者一直处于等待状态
     * 在SpringBoot中消费者这端使用注解获取消息
     */
    @RabbitListener(
        bindings = @QueueBinding(
                //队列的信息,当队列不存在的时候,会自动创建一个队列,并绑定下面的交换机
                value = @Queue(value = "springboot-queue", durable = "true"),
                //交换机的信息
                exchange = @Exchange(value = "springboot-exchange", durable = "true", type = "topic"),
                //路由规则
                key = "#"
        )
    )
    /**
     * RabbitHandler注解,通知SpringBoot该方法用于接收消息,这个方法运行后将处于等待状态,
     * 有新的消息进来就会自动触发该方法处理消息
     *
     *  @param employee  Payload将接收的消息反序列化后注入到Employee对象
     *  @param channel   用于接收消息后进行Ack处理
     *  @param headers   headers获取辅助描述信息
     */
    @RabbitHandler
    public void handleMessage(@Payload Employee employee, Channel channel,
                              @Headers Map<String, Object> headers){
        System.out.println("=====================");
        System.out.println("empno: "+employee.getEmpno() + ", name:" + employee.getName() + ", age:" + employee.getAge());

        long tag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
        try {
            //第一个参数,tag
            //第二个参数,是否批量接收
            channel.basicAck(tag, false);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("=====================");
    }
}
  1. 生产者代码见 SpringBoot整合RabbitMQ生产者代码
  2. 消费者代码见 SpringBoot整合RabbitMQ消费者代码