SpringBoot集成RabbitMQ并实现消息确认机制
原文:https://blog.csdn.net/ctwy291314/article/details/80534604
RabbitMQ安装请参照RabbitMQ应用
不啰嗦直接上代码
目录结构如下:
pom.xml
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.test</groupId>
- <artifactId>RabbitMQ_MQTT</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>RabbitMQ_MQTT</name>
- <url>http://maven.apache.org</url>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.6.RELEASE</version>
- <relativePath /> <!-- lookup parent from repository -->
- </parent>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <java.version>1.8</java.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-amqp</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-devtools</artifactId>
- <optional>true</optional>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <!-- <dependency> <groupId>org.fusesource.mqtt-client</groupId> <artifactId>mqtt-client</artifactId>
- <version>1.12</version> </dependency> -->
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <configuration>
- <fork>true</fork>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </project>
application.properties
- servier.port=8080
- spring.rabbitmq.queues=topic.1,mqtt.test.*,mqtt.test.dd
- spring.rabbitmq.host=127.0.0.1
- spring.rabbitmq.port=5672
- spring.rabbitmq.username=guest
- spring.rabbitmq.password=guest
- spring.rabbitmq.publisher-confirms=true
- spring.rabbitmq.virtual-host=/
Application.java
- package com.gm;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import com.gm.rabbit.CallBackSender;
- @Configuration
- @RestController
- @EnableAutoConfiguration
- @ComponentScan
- @SpringBootApplication
- public class Application {
- @Autowired
- private CallBackSender sender;
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- @RequestMapping("/callback")
- public void callbak() {
- sender.send("topic.baqgl.admin.1", "测试消息");
- }
- }
RabbitConfig.java
- package com.gm.rabbit;
- import java.util.ArrayList;
- import java.util.List;
- import org.springframework.amqp.core.AcknowledgeMode;
- import org.springframework.amqp.core.Binding;
- import org.springframework.amqp.core.BindingBuilder;
- import org.springframework.amqp.core.DirectExchange;
- import org.springframework.amqp.core.Message;
- import org.springframework.amqp.core.Queue;
- import org.springframework.amqp.core.TopicExchange;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
- import org.springframework.amqp.rabbit.connection.ConnectionFactory;
- import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
- import org.springframework.amqp.rabbit.core.RabbitTemplate;
- import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.beans.factory.config.ConfigurableBeanFactory;
- import org.springframework.context.annotation.Scope;
- @Configuration
- public class RabbitConfig {
- @Value("${spring.rabbitmq.host}")
- private String addresses;
- @Value("${spring.rabbitmq.port}")
- private String port;
- @Value("${spring.rabbitmq.username}")
- private String username;
- @Value("${spring.rabbitmq.password}")
- private String password;
- @Value("${spring.rabbitmq.virtual-host}")
- private String virtualHost;
- @Value("${spring.rabbitmq.publisher-confirms}")
- private boolean publisherConfirms;
- @Value("${spring.rabbitmq.queues}")
- private String queues;
- final static String EXCHANGE_NAME = "amq.topic";
- final static String QUEUE_NAME = "topic.baqgl.*.*";
- final static String ROUTING_KEY = "topic.baqgl.#";
- @Bean
- public ConnectionFactory connectionFactory() {
- CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
- connectionFactory.setAddresses(addresses + ":" + port);
- connectionFactory.setUsername(username);
- connectionFactory.setPassword(password);
- connectionFactory.setVirtualHost(virtualHost);
- /** 如果要进行消息回调,则这里必须要设置为true */
- connectionFactory.setPublisherConfirms(publisherConfirms);
- return connectionFactory;
- }
- @Bean
- /** 因为要设置回调类,所以应是prototype类型,如果是singleton类型,则回调类为最后一次设置 */
- @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
- public RabbitTemplate rabbitTemplate() {
- RabbitTemplate template = new RabbitTemplate(connectionFactory());
- return template;
- }
- @Bean
- TopicExchange exchange() {
- return new TopicExchange(EXCHANGE_NAME);
- }
- @Bean
- public Queue queue() {
- return new Queue(QUEUE_NAME, true);
- }
- @Bean
- public Binding binding() {
- return BindingBuilder.bind(queue()).to(exchange()).with(ROUTING_KEY);
- }
- @Bean
- public SimpleMessageListenerContainer messageContainer() {
- /*Queue[] q = new Queue[queues.split(",").length];
- for (int i = 0; i < queues.split(",").length; i++) {
- q[i] = new Queue(queues.split(",")[i]);
- }*/
- SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
- container.setQueues(queue());
- container.setExposeListenerChannel(true);
- container.setMaxConcurrentConsumers(1);
- container.setConcurrentConsumers(1);
- container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
- container.setMessageListener(new ChannelAwareMessageListener() {
- public void onMessage(Message message, com.rabbitmq.client.Channel channel) throws Exception {
- try {
- System.out.println(
- "消费端接收到消息:" + message.getMessageProperties() + ":" + new String(message.getBody()));
- System.out.println("topic:"+message.getMessageProperties().getReceivedRoutingKey());
- // deliveryTag是消息传送的次数,我这里是为了让消息队列的第一个消息到达的时候抛出异常,处理异常让消息重新回到队列,然后再次抛出异常,处理异常拒绝让消息重回队列
- /*if (message.getMessageProperties().getDeliveryTag() == 1
- || message.getMessageProperties().getDeliveryTag() == 2) {
- throw new Exception();
- }*/
- channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); // false只确认当前一个消息收到,true确认所有consumer获得的消息
- } catch (Exception e) {
- e.printStackTrace();
- if (message.getMessageProperties().getRedelivered()) {
- System.out.println("消息已重复处理失败,拒绝再次接收...");
- channel.basicReject(message.getMessageProperties().getDeliveryTag(), true); // 拒绝消息
- } else {
- System.out.println("消息即将再次返回队列处理...");
- channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true); // requeue为是否重新回到队列
- }
- }
- }
- });
- return container;
- }
- }
CallBackSender.java
- package com.gm.rabbit;
- import java.util.UUID;
- 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;
- @Component
- public class CallBackSender implements RabbitTemplate.ConfirmCallback {
- @Autowired
- private RabbitTemplate rabbitTemplate;
- public void send(String topic, String message) {
- rabbitTemplate.setConfirmCallback(this);
- CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
- System.out.println("消息id:" + correlationData.getId());
- //用RabbitMQ发送MQTT需将exchange配置为amq.topic
- this.rabbitTemplate.convertAndSend("amq.topic", topic, message, correlationData);
- }
- public void confirm(CorrelationData correlationData, boolean ack, String cause) {
- System.out.println("消息id:" + correlationData.getId());
- if (ack) {
- System.out.println("消息发送确认成功");
- } else {
- System.out.println("消息发送确认失败:" + cause);
- }
- }
- }
ApplicationTests.java
- package com.gm;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.test.context.junit4.SpringRunner;
- @RunWith(SpringRunner.class)
- @SpringBootTest
- public class ApplicationTests {
- @Test
- public void contextLoads() {
- System.out.println("hello world");
- }
- }
TopicTest.java
- package com.gm.rabbit;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.test.context.junit4.SpringRunner;
- @RunWith(SpringRunner.class)
- @SpringBootTest
- public class TopicTest {
- @Autowired
- private CallBackSender sender;
- @Test
- public void topic() throws Exception {
- sender.send("topic.baqgl.admin.1", "测试消息");
- }
- }
集成MQTT相关配置:
- 创建账号
- rabbitmqctl add_user admin 123456
- 设置用户角色
- rabbitmqctl set_user_tags admin administrator
- 设置用户权限
- rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
- 设置完成后可以查看当前用户和角色(需要开启服务)
- rabbitmqctl list_users
安装插件:
- rabbitmq-plugins enable rabbitmq_management
- rabbitmq-plugins enable rabbitmq_mqtt
默认配置。window下,rabbitmq的配置文件在C:\Users\Administrator\AppData\Roaming\RabbitMQ下。没配置的情况下,采用如下配置:
- [{rabbit, [{tcp_listeners, [5672]}]},
- {rabbitmq_mqtt, [{default_user, <<"admin">>},
- {default_pass, <<"123456">>},
- {allow_anonymous, true},
- {vhost, <<"/">>},
- {exchange, <<"amq.topic">>},
- {subscription_ttl, 1800000},
- {prefetch, 10},
- {ssl_listeners, []},
- %% Default MQTT with TLS port is 8883
- %% {ssl_listeners, [8883]}
- {tcp_listeners, [1883]},
- {tcp_listen_options, [{backlog, 128},
- {nodelay, true}]}]}
- ].
SpringBoot集成RabbitMQ并实现消息确认机制的更多相关文章
- springboot + rabbitmq 用了消息确认机制,感觉掉坑里了
本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近部门号召大伙多组织一些技术分享会,说是要活跃公司的技术氛围,但早就看穿一切的我知道,这 T M 就是为了刷KPI ...
- RabbitMQ (十二) 消息确认机制 - 发布者确认
消费者确认解决的问题是确认消息是否被消费者"成功消费". 它有个前提条件,那就是生产者发布的消息已经"成功"发送出去了. 因此还需要一个机制来告诉生产者,你发送 ...
- RabbitMQ - Publisher的消息确认机制
queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consumer处理呢?毕竟对于 ...
- springboot整合rabbitmq实现生产者消息确认、死信交换器、未路由到队列的消息
在上篇文章 springboot 整合 rabbitmq 中,我们实现了springboot 和rabbitmq的简单整合,这篇文章主要是对上篇文章功能的增强,主要完成如下功能. 需求: 生产者在启 ...
- Spring Boot实战三:集成RabbitMQ,实现消息确认
Spring Boot集成RabbitMQ相比于Spring集成RabbitMQ简单很多,有兴趣了解Spring集成RabbitMQ的同学可以看我之前的<RabbitMQ学习笔记>系列的博 ...
- RabbitMQ 消费者的消息确认机制
消息确认的几点说明: 1. Basic.Ack 发回给 RabbitMQ 以告知,可以将相应 message 从 RabbitMQ 的消息缓存中移除.2. Basic.Ack 未被 consumer ...
- SpringBoot集成rabbitmq(二)
前言 在使用rabbitmq时,我们可以通过消息持久化来解决服务器因异常崩溃而造成的消息丢失.除此之外,我们还会遇到一个问题,当消息生产者发消息发送出去后,消息到底有没有正确到达服务器呢?如果不进行特 ...
- SpringBoot集成RabbitMQ消息队列搭建与ACK消息确认入门
1.RabbitMQ介绍 RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.Rabbi ...
- SpringBoot(九)RabbitMQ安装及配置和使用,消息确认机制
Windows下RabbitMQ安装及配置地址: https://blog.csdn.net/zhm3023/article/details/82217222RabbitMQ(四)订阅模式:https ...
随机推荐
- Centos中查询目录中内容命名ls
首先解释下这块, root代表当前登录用户,localhost代表主机名, ~代表当前主机目录, #代表用户权限 #表示超级用户,$表示普通用户: 查询目录中内容命令 ls (list缩写) ...
- 在oracle中varchar和varchar2有什么区别?
1.varchar2把所有字符都占两字节处理(一般情况下),varchar只对汉字和全角等字符占两字节,数字,英文字符等都是一个字节:2.VARCHAR2把空串等同于null处理,而varchar仍按 ...
- Dev控件删除按钮的两种方式
测试版本15.2.10:在Dev控件中删除按钮空间有两种方式:1.鼠标右键出现Delete选项,这种删除是不完全的删除,只是删除了按钮的显示,实际上按钮还是存在于代码中的.2.用键盘上的Delete键 ...
- JS黑魔法之this, setTimeout/setInterval, arguments
最近发现了JavaScript Garden这个JS黑魔法收集处,不过里面有一些东西并没有说得很透彻,于是边看边查文档or做实验,写了一些笔记,顺手放在博客.等看完了You don't know JS ...
- CCF CSP 201512-2 消除类游戏
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201512-2 消除类游戏 问题描述 消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行 ...
- TI科学家谈浮点DSP未来发展
自十多年前浮点数字信号处理器(DSP)诞生以来,便为实时信号处理提供了算术上更为先进的备选方案.不过,定点器件至今仍是业界的主流.当然低成本是主要原因.定点DSP每器件产品的价格很低,这对大规 ...
- iOS 11开发教程(五)iOS11模拟器介绍二
iOS 11开发教程(五)iOS11模拟器介绍二 3.iOS11模拟器中设置语言 对于不同国家的人来说,使用到的语言是不一样的.一般情况下iOS11模拟器默认使用的English(英语).对于英文不好 ...
- Swift2.0语言教程之下标脚本
Swift2.0语言教程之下标脚本 下标脚本 下标脚本是访问对象.集合或者序列的快速方式.开发者不需要调用实例特定的赋值和访问方法,就可以直接访问所需要的数值.例如在数组中,可以直接使用下标去访问或者 ...
- PHP7.x新特性
1.太空船操作符太空船操作符用于比较两个表达式. 当$a小于. 等于或大于$b时它分别返回-1. 0或1. // Integers echo 1 <=> 1; // 0 echo 1 &l ...
- 线性表之顺序表C++实现
线性表之顺序表 一.头文件:SeqList.h //顺序线性表的头文件 #include<iostream> ; //定义顺序表SeqList的模板类 template<class ...