Spring Boot中的RabbitMQ死信队列魔法:从异常到延迟,一网打尽【RabbitMQ实战 一】
Spring Boot中的RabbitMQ死信队列魔法:从异常到延迟,一网打尽
- 前言
- 第一:基础整合实现
- 第二:处理消息消费异常
- 第三:实现延迟消息处理
- 第四:优雅的消息重试机制
- 第五:异步处理超时消息
- 第六:广泛的实际应用场景
- 总结
前言
在编写现代应用时,我们经常需要处理异步消息。而当这些消息发生异常或者需要延迟处理时,RabbitMQ的死信队列就像一把神奇的钥匙,为我们打开了新的可能性。本文将带你踏入Spring Boot和RabbitMQ的奇妙世界,揭示死信队列的神秘面纱。
第一:基础整合实现
在Spring Boot中整合RabbitMQ并处理消息消费异常,可以通过使用死信队列(Dead Letter Queue)来捕获异常消息。以下是一个简单的Spring Boot应用程序,演示如何实现这个需求:
首先,确保你的项目中引入了Spring Boot和RabbitMQ的依赖。在pom.xml
文件中添加如下依赖:
<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- Spring Boot Starter AMQP --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
</dependencies>
接下来,创建一个配置类用于配置RabbitMQ连接和声明死信队列。例如,创建一个名为RabbitMQConfig
的类:
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitMQConfig {// 定义普通队列@Beanpublic Queue normalQueue() {return new Queue("normal.queue");}// 定义死信队列@Beanpublic Queue deadLetterQueue() {return QueueBuilder.durable("dead-letter.queue").deadLetterExchange("").deadLetterRoutingKey("dead-letter.queue").build();}// 定义交换机@Beanpublic DirectExchange exchange() {return new DirectExchange("exchange");}// 绑定普通队列到交换机@Beanpublic Binding binding(Queue normalQueue, DirectExchange exchange) {return BindingBuilder.bind(normalQueue).to(exchange).with("normal.queue");}// 绑定死信队列到交换机@Beanpublic Binding deadLetterBinding(Queue deadLetterQueue, DirectExchange exchange) {return BindingBuilder.bind(deadLetterQueue).to(exchange).with("dead-letter.queue");}
}
第二:处理消息消费异常
接下来,创建一个消息消费者,同时在消费者中处理异常,将异常消息发送到死信队列。例如,创建一个名为MessageConsumer
的类:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;@Component
public class MessageConsumer {@RabbitListener(queues = "normal.queue")public void consumeMessage(@Payload String message) {try {// 处理消息的业务逻辑// 如果发生异常,将消息发送到死信队列throw new RuntimeException("Simulating an exception during message processing");} catch (Exception e) {// 发送消息到死信队列// 可以在这里记录日志或执行其他操作// 注意:此处是简化的示例,实际情况可能需要根据业务需求进行更复杂的处理// 这里使用默认的交换机和路由键,发送到死信队列// 实际应用中,可能需要根据具体情况进行定制化处理// 可以在RabbitTemplate的convertAndSend方法中指定交换机和路由键// 例如:rabbitTemplate.convertAndSend("exchange", "dead-letter.queue", message);}}
}
以上示例演示了如何在消息消费过程中模拟一个异常,并在异常发生时将消息发送到死信队列。实际应用中,你可能需要根据业务需求进行更复杂的异常处理和日志记录。
请注意,这里使用了默认的交换机和路由键将异常消息发送到死信队列。在实际应用中,你可能需要根据具体情况进行更多的定制化处理。
第三:实现延迟消息处理
要实现消息的延迟投递,可以使用RabbitMQ的TTL(Time-To-Live)和死信队列来实现。下面是一个简单的Spring Boot示例,演示如何配置消息的TTL以实现延迟效果:
首先,在RabbitMQConfig
配置类中添加一个用于设置消息TTL的MessagePostProcessor
:
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitMQConfig {// ... 其他配置 ...// 定义消息的 TTL@Beanpublic MessagePostProcessor messagePostProcessor() {return message -> {// 设置消息的 TTL(单位:毫秒)message.getMessageProperties().setExpiration("5000"); // 5000毫秒即5秒return message;};}
}
在上述配置中,messagePostProcessor
方法返回一个MessagePostProcessor
实例,该实例用于设置消息的TTL。在这个例子中,消息的TTL被设置为5000毫秒(即5秒)。
接下来,在消息的生产者中使用RabbitTemplate
发送消息时,通过convertAndSend
方法添加MessagePostProcessor
:
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MessageProducer {private final RabbitTemplate rabbitTemplate;@Autowiredpublic MessageProducer(RabbitTemplate rabbitTemplate) {this.rabbitTemplate = rabbitTemplate;}public void sendMessage(String message) {// 发送消息,并添加 MessagePostProcessor 设置 TTLrabbitTemplate.convertAndSend("exchange", "normal.queue", message, messagePostProcessor());}
}
在上述例子中,通过convertAndSend
方法发送消息时,使用messagePostProcessor
方法返回的MessagePostProcessor
实例来设置消息的TTL。
最后,在MessageConsumer
中监听死信队列,处理延迟消息:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;@Component
public class MessageConsumer {@RabbitListener(queues = "dead-letter.queue")public void consumeDelayedMessage(@Payload String message) {// 处理延迟消息的业务逻辑System.out.println("Received delayed message: " + message);}
}
在这个例子中,MessageConsumer
通过@RabbitListener
监听死信队列,一旦有延迟消息到达,就会触发consumeDelayedMessage
方法来处理延迟消息的业务逻辑。
这样,通过配置消息的TTL和死信队列,你就实现了延迟消息处理的效果。在实际应用中,可以根据具体需求调整消息的TTL值和处理逻辑。
第四:优雅的消息重试机制
设计可靠的消息重试机制是确保系统在面对消息处理失败时能够自动重试,提高消息的可靠性。以下是一个简单的消息重试机制的实现,利用死信队列进行消息重试。
首先,在RabbitMQConfig
配置类中添加一个用于设置消息重试次数的MessagePostProcessor
:
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitMQConfig {// ... 其他配置 ...// 定义消息的最大重试次数private static final int MAX_RETRY_COUNT = 3;// 定义消息的 TTL@Beanpublic MessagePostProcessor messagePostProcessor() {return message -> {// 设置消息的 TTL(单位:毫秒)message.getMessageProperties().setExpiration("5000"); // 5000毫秒即5秒// 设置消息的最大重试次数message.getMessageProperties().setHeader("x-max-retry-count", MAX_RETRY_COUNT);return message;};}
}
在上述配置中,MAX_RETRY_COUNT
定义了消息的最大重试次数。在messagePostProcessor
方法中,通过setHeader
设置了消息的最大重试次数。
接下来,在消息的消费者中,通过捕获异常来进行消息的重试。当发生异常时,检查消息的重试次数,如果小于最大重试次数,则将消息重新发送到原队列,否则将消息发送到死信队列:
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;@Component
public class MessageConsumer {@RabbitListener(queues = "normal.queue")public void consumeMessage(@Payload String message, Message rabbitMessage) {try {// 处理消息的业务逻辑// 如果发生异常,将消息重试throw new RuntimeException("Simulating an exception during message processing");} catch (Exception e) {handleRetry(message, rabbitMessage);}}private void handleRetry(String message, Message rabbitMessage) {// 获取消息的重试次数Integer retryCount = rabbitMessage.getMessageProperties().getHeader("x-death-retry-count");// 如果重试次数小于最大重试次数,则将消息重新发送到原队列if (retryCount != null && retryCount < getMaxRetryCount()) {System.out.println("Retrying message: " + message);// 在实际应用中,可能需要根据业务需求进行更复杂的重试逻辑// 这里使用默认的交换机和路由键,发送到原队列// 实际应用中,可能需要根据具体情况进行定制化处理rabbitTemplate.convertAndSend("exchange", "normal.queue", message, messagePostProcessor());} else {// 超过最大重试次数,将消息发送到死信队列System.out.println("Max retry count reached. Sending message to dead-letter.queue: " + message);rabbitTemplate.convertAndSend("exchange", "dead-letter.queue", message, messagePostProcessor());}}private int getMaxRetryCount() {// 从配置或其他地方获取最大重试次数return RabbitMQConfig.MAX_RETRY_COUNT;}
}
在上述例子中,consumeMessage
方法模拟了消息处理时的异常。在异常发生时,调用handleRetry
方法进行消息的重试。handleRetry
方法获取消息的重试次数,如果小于最大重试次数,则将消息重新发送到原队列,否则将消息发送到死信队列。
这样,通过设置消息的TTL和利用死信队列,结合消息重试机制,你可以实现一个优雅的消息重试策略,提高系统的可靠性。在实际应用中,你可能需要根据具体需求调整消息的TTL、最大重试次数和处理逻辑。
第五:异步处理超时消息
处理长时间运行的任务时,通常需要考虑超时机制,以避免无限等待。在消息队列中,可以使用死信队列来处理超时消息。以下是一个简单的示例,演示如何使用死信队列处理异步处理超时的消息。
首先,在RabbitMQConfig
配置类中添加一个用于设置消息的TTL和超时队列的配置:
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitMQConfig {// ... 其他配置 ...// 定义消息的 TTLprivate static final long MESSAGE_TTL = 10000; // 10秒// 定义超时队列@Beanpublic Queue timeoutQueue() {return QueueBuilder.durable("timeout.queue").deadLetterExchange("").deadLetterRoutingKey("timeout.queue.dead-letter").ttl(MESSAGE_TTL).build();}// 定义交换机@Beanpublic DirectExchange exchange() {return new DirectExchange("exchange");}// 绑定超时队列到交换机@Beanpublic Binding timeoutBinding(Queue timeoutQueue, DirectExchange exchange) {return BindingBuilder.bind(timeoutQueue).to(exchange).with("timeout.queue");}
}
在上述配置中,MESSAGE_TTL
定义了消息的TTL,这里设置为10秒。timeoutQueue
方法定义了超时队列,并通过ttl
方法设置了队列的TTL。
接下来,在消息的生产者中,使用RabbitTemplate
发送消息时,发送到超时队列:
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MessageProducer {private final RabbitTemplate rabbitTemplate;@Autowiredpublic MessageProducer(RabbitTemplate rabbitTemplate) {this.rabbitTemplate = rabbitTemplate;}public void sendTimeoutMessage(String message) {// 发送消息到超时队列rabbitTemplate.convertAndSend("exchange", "timeout.queue", message);}
}
在上述例子中,通过convertAndSend
方法将消息发送到超时队列。
最后,在消息的消费者中监听死信队列,处理超时消息:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;@Component
public class MessageConsumer {@RabbitListener(queues = "timeout.queue.dead-letter")public void handleTimeoutMessage(@Payload String message) {// 处理超时消息的业务逻辑System.out.println("Received timeout message: " + message);}
}
在这个例子中,MessageConsumer
通过@RabbitListener
监听死信队列,一旦有超时消息到达,就会触发handleTimeoutMessage
方法来处理超时消息的业务逻辑。
通过配置消息的TTL和死信队列,结合异步处理,你可以实现一个可靠的超时处理机制。在实际应用中,你可能需要根据具体需求调整消息的TTL值和处理逻辑。
第六:广泛的实际应用场景
在实际应用中,消息队列和异步消息处理在许多场景中都是非常有用的。以下是一些广泛的实际应用场景:
-
订单支付状态更新:
- 当用户发起支付请求后,可以使用消息队列来异步处理支付状态的更新。
- 消息队列可以将支付成功或失败的消息发送给订单服务,订单服务异步处理并更新订单状态。
- 这种方式可以提高系统的响应速度,避免在支付过程中用户长时间等待。
-
用户通知和提醒:
- 当有新的消息、通知或提醒需要发送给用户时,可以使用消息队列来异步处理。
- 例如,用户注册成功后,系统可以通过消息队列异步发送欢迎邮件或短信给用户。
- 这样可以降低用户注册的响应时间,提升用户体验。
-
邮件发送和异步任务:
- 邮件发送是一个常见的异步任务,可以使用消息队列来处理邮件发送请求。
- 用户触发的某些操作(如密码重置、订单确认等)可能需要发送邮件通知,通过消息队列异步发送邮件可以提高系统的吞吐量。
- 异步任务的其他场景包括数据处理、生成报告等耗时的操作。
-
系统解耦和微服务通信:
- 在微服务架构中,不同服务之间的通信可以通过消息队列来实现解耦。
- 服务之间通过消息队列发送事件,其他服务订阅并响应这些事件,从而实现松耦合的微服务通信。
-
日志收集和分析:
- 将系统产生的日志异步发送到消息队列,以便后续进行集中的日志收集和分析。
- 这有助于监控系统的运行状况、发现问题和进行性能分析。
-
批量处理和数据同步:
- 在需要进行批量处理或数据同步的场景,消息队列可以用于异步触发这些任务。
- 例如,定时异步同步用户数据、商品库存更新等。
这些场景中,消息队列提供了一种解耦和异步处理的机制,有助于提高系统的可伸缩性、稳定性和性能。选择适当的消息队列服务和合适的消息处理策略对于不同场景非常重要。
总结
通过学习本文,你将深入了解如何在Spring Boot应用中高效、灵活地应用RabbitMQ死信队列。实际的代码实现将为你打开处理异步消息的新视角,让你在项目中更加从容地面对各种消息场景。死信队列不再是未知的领域,而是成为你解决异步消息难题的得力助手。开始你的RabbitMQ死信队列之旅吧!
相关文章:
Spring Boot中的RabbitMQ死信队列魔法:从异常到延迟,一网打尽【RabbitMQ实战 一】
Spring Boot中的RabbitMQ死信队列魔法:从异常到延迟,一网打尽 前言第一:基础整合实现第二:处理消息消费异常第三:实现延迟消息处理第四:优雅的消息重试机制第五:异步处理超时消息第六࿱…...
nrm : 镜像源工具npm镜像切换
nrm命令 安装nrm:npm i -g nrm 查看镜像源:nrm ls,带*号的为当前使用的源 添加新镜像:nrm add [镜像源名称] <源的URL路径> 切换镜像源:nrm use [镜像源名称] 删除一个镜像源:nrm del [镜像源名称] …...
Star 10.4k!推荐一款国产跨平台、轻量级的文本编辑器,内置代码对比功能
notepad 相信大家从学习这一行就开始用了,它是开发者/互联网行业的上班族使用率最高的一款轻量级文本编辑器。但是它只能在Windows上进行使用,而且正常来说是收费的(虽然用的是pj的)。 对于想在MacOS、Linux上想使用,…...
iOS 17.2:可以修改消息提示音了
时隔2周之后,苹果今日为开发者预览版用户推送了iOS 17.2 Beta4测试版的更新,已经注册Apple Beta版软件计划的用户只需打开设置--通用--软件更新即可在线OTA升级至最新的iOS 17.2测试版。 本次更新包大小为590M左右,内部版本号为(…...
PTA 一维数组7-3出生年(本题请你根据要求,自动填充“我出生于y年,直到x岁才遇到n个数字都不相同的年份”这句话)
以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y年,直到x岁才遇到n个数字都不相同的…...
【3】基于多设计模式下的同步异步日志系统-设计模式
详细介绍设计模式 单例模式 ⼀个类只能创建⼀个对象,即单例模式,该设计模式可以保证系统中该类只有⼀个实例,并提供⼀个访问它的全局访问点,该实例被所有程序模块共享。⽐如在某个服务器程序中,该服务器的配置信息存放…...
Metasploit的使用和配置
预计更新 第一章 Metasploit的使用和配置 1.1 安装和配置Metasploit 1.2 Metasploit的基础命令和选项 1.3 高级选项和配置 第二章 渗透测试的漏洞利用和攻击方法 1.1 渗透测试中常见的漏洞类型和利用方法 1.2 Metasploit的漏洞利用模块和选项 1.3 模块编写和自定义 第三章 Me…...
测试用例的设计思路
接到提测单后要做的事情: 测试准备阶段 确认提测单内包含的文件、URL地址可以访问确认需求 (迭代目标、用户故事、用户愿望、问题反馈等)确认回归测试范围、更新测试范围、新增测试范围编写测试点思维导图,过程中有问题及时进行沟通与迭代相关人员约一个…...
HCIP——交换综合实验
一、实验拓扑图 二、实验需求 1、PC1和PC3所在接口为access,属于vlan2;PC2/4/5/6处于同一网段,其中PC2可以访问PC4/5/6;但PC4可以访问PC5,不能访问PC6 2、PC5不能访问PC6 3、PC1/3与PC2/4/5/6/不在同一网段 4、所有PC通…...
大学生如何搭建自己的网站
这篇是我在大一的时候,写过的一篇文章。 前言 作为一名大学生,我觉得搭建个人网站很有意义。 这篇博客讲述的是这个寒假,我是如何从零到搭建好个人网站的过程。我提供的主要是具体的思路,也附带了一些零零散散的细节。时间跨度…...
linux 路由表的优先级
[rootlocalhost cc]# ip rule list 0: from all lookup local 32765: from 10.0.19.24 lookup 4096 32766: from all lookup main 32767: from all lookup default 现在有 4 条路由规则,优先级是怎样的,0 代表最低优先级还是最高优先级 在 Linux 的 IP …...
毕业项目分享
大家好,今天给大家分享112个有趣的Python实战项目,可以直接拿来实战练习,涵盖机器学习、爬虫、数据分析、数据可视化、大数据等内容,建议关注、收藏。 项目名称 主要技术 2023招聘数据分析可视化系统爬虫 7种薪资预测模型 Flas…...
Android启动系列之进程杀手--lmkd
本文概要 这是Android系统启动的第三篇文章,本文以自述的方式来讲解lmkd进程,通过本文您将了解到lmkd进程在安卓系统中存在的意义,以及它是如何杀进程的。(文中的代码是基于android13) 我是谁 init:“大…...
tex中的边框
文章目录 利用tcolorbox宏包给公式加框 利用tcolorbox宏包 tcolorbox可以创建一个盒子的环境,例如: \documentclass{article} \usepackage{tcolorbox} \begin{document}\begin{tcolorbox}[left1cm, right1cm, top0.5cm, bottom0.5cm,colbackblue!10!wh…...
面试题库之JAVA基础篇(三)
final 被final修饰的类不可以被继承。被final修改的方法不可以被重写。被final修改的方法,jvm会尝试内联,以提高运行效率。被final修改的变量不可变,如果修改的是引用,那么引用不可变,引用指向的对象内容可变。被fin…...
CTF-虚拟机-QEMU-前置知识-操作流程与源码阅读
文章目录 总览内存PCI设备PCI配置空间前64个字节对应源码Memorry空间的BARIO空间的BAR MMIOPMIOIspci访问PCI设备配置空间中的Memory空间和IO空间MMIOPMIO QQM(qemu object model)简洁概要将 TypeInfo 注册 TypeImpl:ObjectClass的初始化&…...
java成神秘籍第一卷
前言 适合还没有入行小白学习,有些朋友会跑来问我这行的一些问题,下面算是详细系统的整理了一下啦。 全当是学习 复盘 整理 记录了 java成神秘籍第一卷 前言一 前提1 要不要考公,考编,考研2 语言选择3 就业岗位4 目标5 考不考虑…...
golang实现文件上传(高并发+分块+断点续传+加密)
运行视频 // todo 根据前端传递文件加密 func (s *FileProcess) FileProcessEncryptionByFront(file multipart.File, h *multipart.FileHeader) interface{} { //根据字节直接处理文件 这个是前端传递的二进制流s.FileProcessInit() //文件初始化 设置原来文件…...
用HeidiSQL在MySQL中新建用户
用HeidiSQL登录到MySQL数据库,注意登录的时候要使用有权限的用户: 选择工具-》用户管理: 点击左上角的“添加”: 输入用户名、密码,并且分配权限: 点击右边的“添加对象”: 可以根据自己…...
【IPv6】IPv6协议
一、IPv6数据报格式 这是与v4报头的对比 1.8bit的版本保留了,v4版本就是4,v6就是6。 2.v6去除了v4的首部长度字段,因为v6的首部长是固定的40字节。 3.服务类型(Type of Service, ToS)和通信类型(Traffi…...
无需服务器,无需魔法,拥有一个微信机器人就是这么简单
前情提要 还没看过的朋友可以看一下上一篇文章《拥有一个微信机器人总共需要几步?》在这篇文章里,我们提到,创建微信机器人需要一个大前提--你得有一台服务器。现在,不再需要了!没错,上一篇提到的Serverles…...
1、命名空间、C++的复合类型、缺省参数
命名空间 1、命名空间的定义 使用namespace定义,使用作用域限定符::访问 #include <iostream> namespace ICBC{int money 0;void save( int m){money m;} } int main( void ){ICBC::save( 100); std::cout << "工行卡余额:"…...
colab notebook导出为PDF
目录 方法一:使用浏览器打印功能 方法二:使用nbconvert转换 方法三:在线转换 方法一:使用浏览器打印功能 一般快捷键是CTRLP 然后改变目标打印机为另存为PDF 这样就可以将notebook保存为PDF了 方法二:使用nbconver…...
【Python动漫系列】名侦探柯南(完整代码)
文章目录 名侦探柯南环境需求完整代码程序分析系列文章名侦探柯南 《名侦探柯南》是由青山刚昌创作的一部侦探漫画,于1994年开始连载,并被改编为动画、电影、游戏等多种形式。故事讲述了高中生侦探工藤新一在破案时被不良组织所毒害,身体缩小成了一个小学生,为了寻找解药并…...
【matlab】QR分解
QR分解 给定一个mn的矩阵A,其中m≥n,即矩阵A是高矩阵或者是方阵,QR分解将矩阵A分解为两个矩阵Q和R的乘积,其中矩阵Q是一个mn的各列正交的矩阵,即QTQI,矩阵R是一个nn的上三角矩阵,其对角线元素为…...
Liunx系统使用超详细(三)
本篇内容开始逐渐描述有关liunx的各种命令的使用方法! 目录 一、目录和文件区别 1.1目录: 1.2文件: 1.3总结: 二、Linux命令的写法 三、linux命令清屏 四、pwd命令 五、ls命令 5.1 ls: 5.2 ls -l:…...
Kubernetes学习笔记-Part.06 Docker安装
目录 Part.01 Kubernets与docker Part.02 Docker版本 Part.03 Kubernetes原理 Part.04 资源规划 Part.05 基础环境准备 Part.06 Docker安装 Part.07 Harbor搭建 Part.08 K8s环境安装 Part.09 K8s集群构建 Part.10 容器回退 第六章 Docker安装 在master、worker、harbor上均需…...
现在的00后,实在是太卷了......
现在的小年轻真的卷得过分了。前段时间我们公司来了个00年的,工作没两年,跳槽到我们公司起薪18K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天,原来这位小老弟家里条…...
Maven项目目录结构
项目结构 目录说明.ideaIDEA工具的配置文件.mvn用于运行Maven项目src源码文件夹target字节码文件夹.gitignore配置git忽略文件HELP.md自述文件mvnw运行Maven命令(Linux)mvnw.cmd运行Maven命令(Windows)pom.xml依赖管理文件 如图…...
感慨!一路从测试小白到现在的高级测试工程师,方向不对真的很艰辛
1 功能测试人员,也就是我们常常俗称的进行点点点测试工程师。前 1-2 年做功能测试,使用其他人开发的工具进行测试。这个阶段的测试工作都比较初级,严重依赖于别人开发的工具和系统。当系统进行升级换代的时候,强哥会明显的感觉到…...
北京建设安全网络平台87/如何优化标题关键词
目前对消息队列并不了解其原理,本篇文章主要是通过慕课网学习归纳的一些笔记,为后续学习打下基础。 众所周知在对网站设计的时候,会遇到给用户“群发短信”,“订单系统有大量的日志”,“秒杀设计”等,服务器…...
如何开发小程序微信/优化教程网下载
iaas paas SaaS区别差异:白及:以前接触也不懂什么是iaas、saas、paas后来到云厂商去打工之后,才慢慢懂了!云计算的供求链条可以简化为:(大量)终端用户 —— SaaS(软件/服务ÿ…...
网站上推广游戏怎么做/重庆百度竞价开户
转载:https://blog.csdn.net/xiaodanpeng/article/details/53503076 Python 实现 在Linux下,CPU利用率分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行…...
怎么做投票管理系统后台网站/专业软文平台
(给CPP开发者加星标,提升C/C技能)来源:鲸90830https://www.cnblogs.com/whale90830/p/10542361.html1) const 对象的一般形式类型名 const 对象名[(构造实参表列)];const 类型名 对象名[(构造实参表列)];注意:常对象必须要有初值(因为以后不能…...
建设企业网站登录入口/外贸平台排名
前言20世纪90年代,互联网中最兴的一个产物,“网吧”算是人尽皆知的吧!1999年--2005年网吧走到了高峰时期,它高峰到什么样子呢?就是疯狂到网民们在网吧门口,排队等着上网的程度,当时有一位人人皆…...
川沙网站建设/竞价推广培训课程
wpf阻止键盘快捷键altspace,altF4 原文:wpf阻止键盘快捷键altspace,altF4/// <summary> /// 阻止 altf4和altspace 按键 /// </summary> /// <param name"e"></param> protected overrid…...