SpringBoot整合RabbitMQ快速实战

目录

引入依赖

配置文件

不同模式下使用springboot收发消息

直连模式

生产者

消费者

Fanout模式

生产者

消费者

Topic主题模式

生产者

消费者

Headers模式

生产者

消费者

补充Quorum队列

生产者

消费者


引入依赖

XML 复制代码
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

注意下版本。不同版本下的配置方式会有变化。


配置文件

所有的基础运行环境都在application.properties中进行配置。所有配置以spring.rabbitmq开头。通常按照示例进行一些基础的必要配置就可以跑了。

javascript 复制代码
server.port=8080
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/mirror

# 单词推送消息数量
spring.rabbitmq.listener.simple.prefetch=1
# 消费者的消费线程数量
spring.rabbitmq.listener.simple.concurrency=5
# 消费者的最大线程数量
spring.rabbitmq.listener.simple.max-concurrency=10
# 手动确认消息
spring.rabbitmq.listener.simple.acknowledge-mode=none

不同模式下使用springboot收发消息

工具类

java 复制代码
public class MyConstants {

    public static final String QUEUE_QUORUM = "quorumQueue";
    public static final String QUEUE_STREAM = "streamQueue";
    //direct模式,直接发送到队列
    public static final String QUEUE_DIRECT = "directqueue";
    //fanout模式
    public static final String EXCHANGE_FANOUT = "fanoutExchange";
    public static final String QUEUE_FANOUT_Q1 = "fanout.q1";
    public static final String QUEUE_FANOUT_Q2 = "fanout.q2";
    public static final String QUEUE_FANOUT_Q3 = "fanout.q3";
    public static final String QUEUE_FANOUT_Q4 = "fanout.q4";
    //topic模式
    public static final String EXCHANGE_TOPIC = "topicExchange";
    public static final String QUEUE_TOPIC1 = "hunan.eco";
    public static final String QUEUE_TOPIC2 = "hunan.IT";
    public static final String QUEUE_TOPIC3 = "hebei.eco";
    public static final String QUEUE_TOPIC4 = "hebei.IT";
    //header模式
    public static final String EXCHANGE_HEADER = "headerExchange";
    public static final String QUEUE_TXTYP1 = "txTyp1";
    public static final String QUEUE_BUSTYP1 = "busTyp1";
    public static final String QUEUE_TXBUSTYP1 = "txbusTyp1";

}

直连模式

java 复制代码
/**
 * 直连模式只需要声明队列,所有消息都通过队列转发。
 */
@Configuration
public class DirectConfig {

	@Bean
	public Queue directQueue() {
		return new Queue(MyConstants.QUEUE_DIRECT);
	}
}
生产者
java 复制代码
	@ApiOperation(value="direct发送接口",notes="直接发送到队列。task模式")
	@GetMapping(value="/directSend")
	public Object directSend(String message) throws AmqpException, UnsupportedEncodingException {
		//设置部分请求参数
		MessageProperties messageProperties = new MessageProperties();
		messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
		messageProperties.setPriority(2);
		//设置消息转换器,如json
		rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
		//将对象转换成json再发送。
//		rabbitTemplate.convertandsend("",Object);
		//发消息
		rabbitTemplate.send("directqueue",new Message(message.getBytes("UTF-8"),messageProperties));
		return "message sended : "+message;
	}
消费者
java 复制代码
	//直连模式的多个消费者,会分到其中一个消费者进行消费。类似task模式
	//通过注入RabbitContainerFactory对象,来设置一些属性,相当于task里的channel.basicQos
	@RabbitListener(queues=MyConstants.QUEUE_DIRECT,containerFactory="qos_4")
	public void directReceive22(Message message, Channel channel, String messageStr) {
		System.out.println("consumer1 received message : " +messageStr);
	}

	@RabbitListener(queues=MyConstants.QUEUE_DIRECT)
	public void directReceive2(String message) {
		System.out.println("consumer2 received message : " +message);
	}
java 复制代码
@Configuration
public class RabbitmqConfig {
    @Bean(name="qos_4")
    public SimpleRabbitListenerContainerFactory getSimpleRabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setMaxConcurrentConsumers(4);
        factory.setConnectionFactory(connectionFactory);
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);//手动确认
        return factory;
    }
}

Fanout模式

java 复制代码
/**
 * Fanout模式需要声明exchange,并绑定queue,由exchange负责转发到queue上。
 */
@Configuration
public class FanoutConfig {

	//声明队列
	@Bean
	public Queue fanoutQ1() {
		return new Queue(MyConstants.QUEUE_FANOUT_Q1);
	}
	@Bean
	public Queue fanoutQ2() {
		return new Queue(MyConstants.QUEUE_FANOUT_Q2);
	}
	@Bean
	public Queue fanoutQ3() {
		return new Queue(MyConstants.QUEUE_FANOUT_Q3);
	}
	@Bean
	public Queue fanoutQ4() {
		return new Queue(MyConstants.QUEUE_FANOUT_Q4);
	}
	//声明exchange
	@Bean
	public FanoutExchange setFanoutExchange() {
		return new FanoutExchange(MyConstants.EXCHANGE_FANOUT);
	}
	//声明Binding,exchange与queue的绑定关系
	@Bean
	public Binding bindQ1() {
		return BindingBuilder.bind(fanoutQ1()).to(setFanoutExchange());
	}
	@Bean
	public Binding bindQ2() {
		return BindingBuilder.bind(fanoutQ2()).to(setFanoutExchange());
	}
	@Bean
	public Binding bindQ3() {
		return BindingBuilder.bind(fanoutQ3()).to(setFanoutExchange());
	}
	@Bean
	public Binding bindQ4() {
		return BindingBuilder.bind(fanoutQ4()).to(setFanoutExchange());
	}
	
}
生产者
java 复制代码
	@ApiOperation(value="fanout发送接口",notes="发送到fanoutExchange。消息将往该exchange下的所有queue转发")
	@GetMapping(value="/fanoutSend")
	public Object fanoutSend(String message) throws AmqpException, UnsupportedEncodingException {
		MessageProperties messageProperties = new MessageProperties();
		messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
		//fanout模式只往exchange里发送消息。分发到exchange下的所有queue
		rabbitTemplate.send(MyConstants.EXCHANGE_FANOUT, "", new Message(message.getBytes("UTF-8"),messageProperties));

		Message message2 = MessageBuilder.withBody(message.getBytes()).setMessageId(UUID.randomUUID().toString()).build();
		rabbitTemplate.send(message2);
		return "message sended : "+message;
	}
消费者
java 复制代码
	//fanout模式接收还是只指定队列
	@RabbitListener(queues=MyConstants.QUEUE_FANOUT_Q1)
	public void fanoutReceiveq1(String message) {
		System.out.println("fanoutReceive q1 received message : " +message);
	}
	@RabbitListener(queues=MyConstants.QUEUE_FANOUT_Q2)
	public void fanoutReceiveq2(String message) {
		System.out.println("fanoutReceive q2 received message : " +message);
	}
	@RabbitListener(queues=MyConstants.QUEUE_FANOUT_Q3)
	public void fanoutReceiveq3(String message) {
		System.out.println("fanoutReceive q3 received message : " +message);
	}
	@RabbitListener(queues=MyConstants.QUEUE_FANOUT_Q4)
	public void fanoutReceiveq4(String message) {
		System.out.println("fanoutReceive q4 received message : " +message);
	}

Topic主题模式

java 复制代码
@Configuration
public class TopicConfig {

	//声明队列
	@Bean
	public Queue topicQ1() {
		return new Queue(MyConstants.QUEUE_TOPIC1);
	}
	@Bean
	public Queue topicQ2() {
		return new Queue(MyConstants.QUEUE_TOPIC2);
	}
	@Bean
	public Queue topicQ3() {
		return new Queue(MyConstants.QUEUE_TOPIC3);
	}
	@Bean
	public Queue topicQ4() {
		return new Queue(MyConstants.QUEUE_TOPIC4);
	}
	//声明exchange
	@Bean
	public TopicExchange setTopicExchange() {
		return new TopicExchange(MyConstants.EXCHANGE_TOPIC);
	}
	//声明binding,需要声明一个roytingKey
	@Bean
	public Binding bindTopicHebei1() {
		return BindingBuilder.bind(topicQ1()).to(setTopicExchange()).with("hunan.*");
	}
	@Bean
	public Binding bindTopicHebei2() {
		return BindingBuilder.bind(topicQ2()).to(setTopicExchange()).with("*.IT");
	}
	@Bean
	public Binding bindTopicHebei3() {
		return BindingBuilder.bind(topicQ3()).to(setTopicExchange()).with("*.eco");
	}
	@Bean
	public Binding bindTopicHebei4() {
		return BindingBuilder.bind(topicQ4()).to(setTopicExchange()).with("hebei.*");
	}
	
}
生产者
java 复制代码
@ApiOperation(value="topic发送接口",notes="发送到topicExchange。exchange转发消息时,会往routingKey匹配的queue发送,*代表一个单词,#代表0个或多个单词。")
	@ApiImplicitParam(name="routingKey",value="路由关键字")
	@GetMapping(value="/topicSendHunanIT")
	public Object topicSend(String routingKey,String message) throws AmqpException, UnsupportedEncodingException {
		if(null == routingKey) {
			routingKey="hebei.IT";
		}
		MessageProperties messageProperties = new MessageProperties();
		messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
		//fanout模式只往exchange里发送消息。分发到exchange下的所有queue
		rabbitTemplate.send("topicExchange", routingKey, new Message(message.getBytes("UTF-8"),messageProperties));
		return "message sended : routingKey >"+routingKey+";message > "+message;
	}
消费者
java 复制代码
	//topic Receiver
	//注意这个模式会有优先匹配原则。例如发送routingKey=hunan.IT,那匹配到hunan.*(hunan.IT,hunan.eco),之后就不会再去匹配*.IT(hebei.IT)
	@RabbitListener(queues=MyConstants.QUEUE_TOPIC1)
	public void topicReceiveq1(String message) {
		System.out.println("topic hunan.eco received message : " +message);
	}
	@RabbitListener(queues=MyConstants.QUEUE_TOPIC2)
	public void topicReceiveq2(String message) {
		System.out.println("topic hunan.IT received message : " +message);
	}
	@RabbitListener(queues=MyConstants.QUEUE_TOPIC3)
	public void topicReceiveq3(String message) {
		System.out.println("topic hebei.eco received message : " +message);
	}
	@RabbitListener(queues=MyConstants.QUEUE_TOPIC4)
	public void topicReceiveq4(String message) {
		System.out.println("topic hebei.IT received message : " +message);
	}

Headers模式

java 复制代码
@Configuration
public class HeaderConfig {

	//声明queue
	@Bean
	public Queue headQueueTxTyp1() {
		return new Queue(MyConstants.QUEUE_TXTYP1);
	}
	@Bean
	public Queue headQueueBusTyp1() {
		return new Queue(MyConstants.QUEUE_BUSTYP1);
	}
	@Bean
	public Queue headQueueTxBusTyp() {
		return new Queue(MyConstants.QUEUE_TXBUSTYP1);
	}
	//声明exchange
	@Bean
	public HeadersExchange setHeaderExchange() {
		return new HeadersExchange(MyConstants.EXCHANGE_HEADER);
	}
	//声明Binding
	//绑定header中txtyp=1的队列。header的队列匹配可以用mathces和exisits
	@Bean
	public Binding bindHeaderTxTyp1() {
		return BindingBuilder.bind(headQueueTxTyp1()).to(setHeaderExchange()).where("txTyp").matches("1");
	}
	//绑定Header中busTyp=1的队列。
	@Bean 
	public Binding bindHeaderBusTyp1() {
		return BindingBuilder.bind(headQueueBusTyp1()).to(setHeaderExchange()).where("busTyp").matches("1");
	}
	//绑定Header中txtyp=1或者busTyp=1的队列。
	@Bean 
	public Binding bindHeaderTxBusTyp1() {
		Map<String,Object> condMap = new HashMap<>();
		condMap.put("txTyp", "1");
		condMap.put("busTyp", "1");
//		return BindingBuilder.bind(headQueueTxBusTyp()).to(setHeaderExchange()).whereAny(new String[] {"txTyp","busTyp"}).exist();
		return BindingBuilder.bind(headQueueTxBusTyp()).to(setHeaderExchange()).whereAny(condMap).match();
	}
}
生产者
java 复制代码
@ApiOperation(value="header发送接口",notes="发送到headerExchange。exchange转发消息时,不再管routingKey,而是根据header条件进行转发。")
	@GetMapping(value="/headerSend")
	public Object headerSend(String txTyp,String busTyp,String message) throws AmqpException, UnsupportedEncodingException {
		if(null == txTyp) {
			txTyp="0";
		}
		if(null == busTyp) {
			busTyp="0";
		}
		MessageProperties messageProperties = new MessageProperties();
		messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
		messageProperties.setHeader("txTyp", txTyp);
		messageProperties.setHeader("busTyp", busTyp);
		//fanout模式只往exchange里发送消息。分发到exchange下的所有queue
		rabbitTemplate.send("headerExchange", "uselessRoutingKey", new Message(message.getBytes("UTF-8"),messageProperties));
		return "message sended : txTyp >"+txTyp+";busTyp > "+busTyp;
	}
消费者
java 复制代码
    //header receiver
	//这个模式不再根据routingKey转发,而是根据header中的匹配条件进行转发
	@RabbitListener(queues=MyConstants.QUEUE_TXTYP1)
	public void headerReceiveq1(String message) {
		System.out.println("header txTyp1 received message : " +message);
	}
	@RabbitListener(queues=MyConstants.QUEUE_BUSTYP1)
	public void headerReceiveq2(String message) {
		System.out.println("header busTyp1 received message : " +message);
	}
	@RabbitListener(queues=MyConstants.QUEUE_TXBUSTYP1)
	public void headerReceiveq3(String message) {
		System.out.println("header txbusTyp1 received message : " +message);
	}

补充Quorum队列

java 复制代码
/**
 * @desc 声明一个Quorum队列
 */
@Configuration
public class QuorumConfig {
    @Bean
    public Queue quorumQueue() {
        Map<String,Object> params = new HashMap<>();
        params.put("x-queue-type","quorum");

        return new Queue(MyConstants.QUEUE_QUORUM,true,false,false,params);
    }
}
生产者
java 复制代码
	@ApiOperation(value="quorum队列发送接口",notes="直接发送到队列。Quorum队列")
	@GetMapping(value="/directQuorum")
	public Object directQuorum(String message) throws AmqpException, UnsupportedEncodingException {
		//设置部分请求参数
		MessageProperties messageProperties = new MessageProperties();
		messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
		messageProperties.setPriority(2);
		//设置消息转换器,如json
		rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
		//将对象转换成json再发送。
//		rabbitTemplate.convertandsend("",Object);
		//发消息
		rabbitTemplate.send(MyConstants.QUEUE_QUORUM,new Message(message.getBytes("UTF-8"),messageProperties));
		return "message sended : "+message;
	}
消费者
java 复制代码
	@RabbitListener(queues = MyConstants.QUEUE_QUORUM)
	public void quorumReceiver(String message){
		System.out.println("quorumReceiver received message : "+ message);
	}
相关推荐
生擒小朵拉6 分钟前
STM32添加库函数
java·javascript·stm32
Z_z在努力12 分钟前
【杂类】Spring 自动装配原理
java·spring·mybatis
程序员爱钓鱼24 分钟前
Go语言实战案例-开发一个Markdown转HTML工具
前端·后端·go
小小菜鸡ing40 分钟前
pymysql
java·服务器·数据库
getapi42 分钟前
shareId 的产生与传递链路
java
桦说编程1 小时前
爆赞!完全认同!《软件设计的哲学》这本书深得我心
后端
thinktik1 小时前
还在手把手教AI写代码么? 让你的AWS Kiro AI IDE直接读飞书需求文档给你打工吧!
后端·serverless·aws
我没想到原来他们都是一堆坏人2 小时前
(未完待续...)如何编写一个用于构建python web项目镜像的dockerfile文件
java·前端·python
沙二原住民2 小时前
提升数据库性能的秘密武器:深入解析慢查询、连接池与Druid监控
java·数据库·oracle