依赖

  • MAVEN配置pom.xml
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  • Gradle配置build.gradle
compile('org.springframework.boot:spring-boot-starter-amqp')

连接配置

得益于spring boot的约定大于配置,只需要在application.yml加入下面配置即可。

spring:
  rabbitmq:
    host: host
    port: port
    username: admin
    password: passwd

简单自定义RabbitTemplate和Queue配置

默认的配置还是略显不足,增加序列化配置如下:

@Configuration
public class QueueConfig {

    /**
     * 自动注入为SimpleRabbitListenerContainerFactory的消息序列化转换器
     */
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
    * 持久化交换机
    */
    @Bean(name = "exchange")
    public FanoutExchange exchange() {
        return new FanoutExchange("exchange1", true, false);
    }

    /**
    * 持久化队列
    */
    @Bean
    public Queue queue() {
        return new Queue("queue", true);
    }

    /**
     * 将队列和exchange绑定
     *
     * @return binding
     */
    @Bean
    Binding bindingSmsExchangeSmsQueue() {
        return BindingBuilder.bind(queue()).to(exchange());
    }

}

特殊延时队列的配置

延时队列的用法这里就不详细说了,参考Spring Boot与RabbitMQ结合实现延迟队列的示例,有些场景如未支付订单30分钟过期等,可通过延时队列实现

    @Bean
    public Queue delayQueue(){
        return QueueBuilder.durable("delayQueue")                      //队列名称
                .withArgument("x-message-ttl",10000)                      //死信时间
                .withArgument("x-dead-letter-exchange", "")            //死信重新投递的交换机
                .withArgument("x-dead-letter-routing-key", "queue")//路由到队列的routingKey
                .build();
    }

启动应用测试一下

启动应用,在rabbit管理web查看所有队列

  • 所有队列 
  • 查看delayQueue详情,框框中为延时配置  将"x-message-ttl"参数改成20000重启发现问题,控制队列里面的参数也没有修改成功 

修改带参数队列失败的问题

问题分析

根据日志提示,队列已经存在而且参数不一致导致,然后查看源码在RabbitAdmin发现下面代码,在创建队列失败的时候会调用logOrRethrowDeclarationException方法,logOrRethrowDeclarationException方法中发布了一个DeclarationExceptionEvent事件,到这里解决思路有,监听这个事件,然后删除相应的队列   想学习更多java知识的朋友可以进群:874811168 一起学习 还有全套的免费资料领取

	private DeclareOk[] declareQueues(final Channel channel, final Queue... queues) throws IOException {
		List<DeclareOk> declareOks = new ArrayList<DeclareOk>(queues.length);
		for (int i = 0; i < queues.length; i++) {
			Queue queue = queues[i];
			if (!queue.getName().startsWith("amq.")) {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("declaring Queue '" + queue.getName() + "'");
				}
				try {
					try {
						DeclareOk declareOk = channel.queueDeclare(queue.getName(), queue.isDurable(),
								queue.isExclusive(), queue.isAutoDelete(), queue.getArguments());
						declareOks.add(declareOk);
					}
					catch (IllegalArgumentException e) {
						if (this.logger.isDebugEnabled()) {
							this.logger.error("Exception while declaring queue: '" + queue.getName() + "'");
						}
						try {
							if (channel instanceof ChannelProxy) {
								((ChannelProxy) channel).getTargetChannel().close();
							}
						}
						catch (TimeoutException e1) {
						}
						throw new IOException(e);
					}
				}
				catch (IOException e) {
					logOrRethrowDeclarationException(queue, "queue", e);
				}
			}
			else if (this.logger.isDebugEnabled()) {
				this.logger.debug(queue.getName() + ": Queue with name that starts with 'amq.' cannot be declared.");
			} 想学习更多java知识的朋友可以进群:874811168 一起学习 还有全套的免费资料领取
		}
		return declareOks.toArray(new DeclareOk[declareOks.size()]);
	}

	private <T extends Throwable> void logOrRethrowDeclarationException(Declarable element, String elementType, T t)
			throws T {
		DeclarationExceptionEvent event = new DeclarationExceptionEvent(this, element, t);
		this.lastDeclarationExceptionEvent = event;
		if (this.applicationEventPublisher != null) {
			this.applicationEventPublisher.publishEvent(event);
		}
		if (this.ignoreDeclarationExceptions || (element != null && element.isIgnoreDeclarationExceptions())) {
			if (this.logger.isDebugEnabled()) {
				this.logger.debug("Failed to declare " + elementType
						+ ": " + (element == null ? "broker-generated" : element)
						+ ", continuing...", t);
			}
			else if (this.logger.isWarnEnabled()) {
				Throwable cause = t;
				if (t instanceof IOException && t.getCause() != null) {
					cause = t.getCause();
				}
				this.logger.warn("Failed to declare " + elementType
						+ ": " + (element == null ? "broker-generated" : element)
						+ ", continuing... " + cause);
			}
		}
		else {
			throw t;
		}
	}

解决方法

写一个DeclarationExceptionEvent事件监听,处理创建失败的队列,既删除掉

@Component
public class DeclarationExceptionEventListener {
 想学习更多java知识的朋友可以进群:874811168 一起学习 还有全套的免费资料领取
    @Autowired
    private AmqpAdmin rabbitAdmin;

    @EventListener(classes = DeclarationExceptionEvent.class)
    public void listen(DeclarationExceptionEvent event) {
        final Declarable declarable = event.getDeclarable();
        if (declarable instanceof Queue) {
            final Queue queue = (Queue) declarable;
            rabbitAdmin.deleteQueue(queue.getName());
        }
    }
}

改完重启应用,只有一条异常日志(原来4条),还有一条的原因是第一次创建失败发布事件,我们监听了事件进行处理。查看rabbit控制台,参数修改成功。

RabbitMQ进阶使用-延时队列的配置(Spring Boot)的更多相关文章

  1. RabbitMQ学习之延时队列

    原帖参考:http://www.cnblogs.com/telwanggs/p/7124687.html?utm_source=itdadao&utm_medium=referral http ...

  2. (转) RabbitMQ学习之延时队列

    http://blog.csdn.net/zhu_tianwei/article/details/53563311 在实际的业务中我们会遇见生产者产生的消息,不立即消费,而是延时一段时间在消费.Rab ...

  3. C#通过rabbitmq实现定时任务(延时队列)

    本文主要讲解如何通过RabbitMQ实现定时任务(延时队列) 环境准备 需要在MQ中进行安装插件 地址链接 插件介绍地址:https://www.rabbitmq.com/blog/2015/04/1 ...

  4. RabbitMQ:伪延时队列

    目录 一.什么是延时队列 二.RabbitMQ实现 三. 延时队列的问题 四.解决RabbitMQ的伪延时方案 ps:伪延时队列先卖个关子,我们先了解下延时队列. 一.什么是延时队列 所谓延时队列是指 ...

  5. 在IDEA中配置spring boot项目的热更新

    在我使用IDEA的过程中,我发现Spring Boot项目本来自带的一个热部署工具无法使用,这里在参考各家博客后给出解决方案: 修改POM 首先POM文件需要包含spring boot的热部署工具,m ...

  6. Linux系统CentOS 7配置Spring Boot运行环境

    从阿里云新买的一台Linux服务器,用来部署SpringBoot应用,由于之前一直使用Debian版本,环境配置有所不同,也较为繁琐,本文主要介绍CentOS下配置SpringBoot环境的过程 新建 ...

  7. vs code 配置spring boot开发环境

    一.环境变量 jdk环境变量一键设置 管理員运行 - 一支小白 - 博客园https://www.cnblogs.com/startnow/p/7416533.html 二.安装插件 1.Java E ...

  8. 如何配置Spring Boot Tomcat

    1.概述 Spring Boot Web应用程序默认包含预配置的嵌入式Web服务器.但在某些情况下,我们要修改默认配置以满足自定义要求. 在本教程中,我们将介绍通过application.proper ...

  9. spring boot:基于profile的多环境配置(spring boot 2.3.4)

    一,为什么要进行多环境配置? 1,没有人会在生产环境中进行开发和测试, 所以通常会有多个环境的划分: 工程师本地的开发环境 进行测试的测试环境 最终上线的生产环境 每个环境对应不同的数据库/缓存等数据 ...

随机推荐

  1. JAVA基础知识总结:十七

    一.转换流 作用:实现将字节流转换为字符流 a.InputStreamReader:字节字符转换输入流:字节输入流----->字符输入流 b.OutputStreamWriter:字节字符转换输 ...

  2. Python3 操作Excel

    首先说明一下 在处理大文件时,openpyxl 的性能不如 xlrd,xlwt等.所以可以读取的时候使用xlrd,写的时候用openpyxl. 今天遇到一个使用场景:excel存放的是一条条用例,包含 ...

  3. 猫眼电影爬取(二):requests+beautifulsoup,并将数据存储到mysql数据库

    上一篇通过requests+正则爬取了猫眼电影榜单,这次通过requests+beautifulsoup再爬取一次(其实这个网站更适合使用beautifulsoup库爬取) 1.先分析网页源码 可以看 ...

  4. 雷林鹏分享:C# 环境

    C# 环境 在这一章中,我们将讨论创建 C# 编程所需的工具.我们已经提到 C# 是 .Net 框架的一部分,且用于编写 .Net 应用程序.因此,在讨论运行 C# 程序的可用工具之前,让我们先了解一 ...

  5. Bayesian generalized linear model (GLM) | 贝叶斯广义线性回归实例

    一些问题: 1. 什么时候我的问题可以用GLM,什么时候我的问题不能用GLM? 2. GLM到底能给我们带来什么好处? 3. 如何评价GLM模型的好坏? 广义线性回归啊,虐了我快几个月了,还是没有彻底 ...

  6. English Voice of <<if were a boy >>

    <if i were a boy>中英文歌词: If I were a boy 如果我是个男孩 Even just for a day 就算只是一天 I' roll out of bed ...

  7. 利用WCF实现上传下载文件服务

    使用WCF上传文件           在WCF没出现之前,我一直使用用WebService来上传文件,我不知道别人为什么要这么做,因为我们的文件服务器和网站后台和网站前台都不在同一个机器,操作人员觉 ...

  8. C#使用 System.Net.Mail发送邮件功能

    .NET 里包含了很多很丰富的邮件发送与接受的API在 System.Net.Mail命名空间里,使得我们开发发送和接受邮件相关功能变得简单,下面是一个简单发送邮件的功能: private void ...

  9. LeetCode--014--最长公共前缀(java)

    编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...

  10. liunx权限管理之高级权限

    高级权限 suid,sgid,sticky ======================================================== 文件权限管理之:高级权限 问题1: 为什么 ...