RabbitMQ使用案例
一.发布与订阅模式(队列-->交换机)
yml配置:
server:port: 8088
spring:rabbitmq:host: 127.0.0.1port: 5672username: guestpassword: guestpublisher-confirm-type: correlated #消息确认方式,通过 correlated 来确认(将来的消息中才会带 correlation_id,只有通过 correlation_id 我们才能将发送的消息和返回值之间关联起来)publisher-returns: true #开启发送失败退回#1.开启 confirm 确认机制
maven依赖:
<!--rabbitmq--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
1.配置类:
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author :jerry* @date :Created in 2021/12/29 13:58* @description:MQ配置* @version: V1.1*/
@Configuration
public class RabbitConfig {public static final String RPC_QUEUE1 = "queue_1"; //通道1public static final String RPC_QUEUE2 = "queue_2"; //通道2public static final String RPC_EXCHANGE = "rpc_exchange"; // 交换机/*** 设置消息发送RPC队列*/@BeanQueue msgQueue() {return new Queue(RPC_QUEUE1);}/*** 设置返回队列*/@BeanQueue replyQueue() {return new Queue(RPC_QUEUE2);}/*** 设置交换机*/@BeanTopicExchange exchange() {return new TopicExchange(RPC_EXCHANGE);}/*** 请求队列和交换器绑定*/@BeanBinding msgBinding() {return BindingBuilder.bind(msgQueue()).to(exchange()).with(RPC_QUEUE1);}/*** 返回队列和交换器绑定*/@BeanBinding replyBinding() {return BindingBuilder.bind(replyQueue()).to(exchange()).with(RPC_QUEUE2);}/*** 使用 RabbitTemplate发送和接收消息* 并设置回调队列地址*/@BeanRabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate template = new RabbitTemplate(connectionFactory);template.setReplyAddress(RPC_QUEUE2);template.setReplyTimeout(6000);return template;}/*** 给返回队列设置监听器*/@BeanSimpleMessageListenerContainer replyContainer(ConnectionFactory connectionFactory) {SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.setQueueNames(RPC_QUEUE2);container.setMessageListener(rabbitTemplate(connectionFactory));return container;}
}
2.生产者
import com.yl.config.RabbitConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;/*** @author :jerry* @date :Created in 2021/12/29 14:02* @description:MQ生产者* @version: V1.1*/
@Slf4j
@RestController
public class RpcClientController {@Autowiredprivate RabbitTemplate rabbitTemplate;@GetMapping("/send")public String send(String message) {// 创建消息对象Message newMessage = MessageBuilder.withBody(message.getBytes()).build();log.info("生产者发送消息----->>>>>", newMessage);//客户端发送消息Message result = rabbitTemplate.sendAndReceive(RabbitConfig.RPC_EXCHANGE, RabbitConfig.RPC_QUEUE1, newMessage);String response = "";if (result != null) {// 获取已发送的消息的 correlationIdString correlationId = newMessage.getMessageProperties().getCorrelationId();log.info("生产者----->>>>>{}", correlationId);// 获取响应头信息HashMap<String, Object> headers = (HashMap<String, Object>) result.getMessageProperties().getHeaders();// 获取 server 返回的消息 idString msgId = (String) headers.get("spring_returned_message_correlation");if (msgId.equals(correlationId)) {response = new String(result.getBody());log.info("生产者发送消息----->>>>>:{}", response);}}return response;}
}
3.消费者
import com.yl.config.RabbitConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.UnsupportedEncodingException;/*** @author :jerry* @date :Created in 2021/12/29 14:04* @description:MQ消费者* @version: V1.1*/
@Slf4j
@Component
public class RpcServerController {@Autowiredprivate RabbitTemplate rabbitTemplate;@RabbitListener(queues = RabbitConfig.RPC_QUEUE1)public void process(Message msg) throws UnsupportedEncodingException {String message=new String(msg.getBody(),"UTF-8");log.info("消费者消费消息的消息体:{}----->>>>>"+message);Message response = MessageBuilder.withBody(("i'm receive:"+new String(msg.getBody())).getBytes()).build();CorrelationData correlationData = new CorrelationData(msg.getMessageProperties().getCorrelationId());rabbitTemplate.sendAndReceive(RabbitConfig.RPC_EXCHANGE, RabbitConfig.RPC_QUEUE2, response, correlationData);}
}
postmain:http://localhost:8088/send?message=听闻广陵不知寒,大雪龙骑下江南
结果:
二.路由模式(路由--->交换机)
yml配置:
server:port: 8084
spring:rabbitmq:host: 127.0.0.1port: 5672username: guestpassword: guestpublisher-confirms: true #1.开启 confirm 确认机制publisher-returns: true #2.开启 return 确认机制#3.设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数template:mandatory: true
maven配置:
<!--rabbitmq--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
1.RabbitMQ配置
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author :jerry* @date :Created in 2021/12/28 17:38* @description:RabbitMQ配置* @version: V1.1*/
@Configuration
public class RabbitQueueConfig {/*** 方式二:* 通道--->交换机---->路由模式* */public static final String QUEUE_NAME="rollback-queue"; //通道public static final String EXCHANGE_NAME="rollback-exchange"; //交换机public static final String ROUTINGKEY_NAME="rollback-routingkey"; //路由/*---------------------------------方式二-------------------------------------------------*//*** 1.设置消息发送RPC队列* */@Beanpublic Queue queue(){return new Queue(QUEUE_NAME,true);}/*** 2.设置交换机*/@Beanpublic DirectExchange directExchange(){return new DirectExchange(EXCHANGE_NAME);}/*** 3.绑定路由*/@Beanpublic Binding binding(){return BindingBuilder.bind(queue()).to(directExchange()).with(ROUTINGKEY_NAME);}
}
2.重写RabbitTemplate,创建RabbitTemplateConfig
配置类(手动确认消费)
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author :jerry* @date :Created in 2021/12/29 11:10* @description:* @version: V1.1*/@Configuration
@Slf4j
public class RabbitTemplateConfig {//第二种方式final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {log.info("ConfirmCallback,相关数据:{}", correlationData);log.info("ConfirmCallback,确认消息:{}", ack);log.info("ConfirmCallback,原因:{}", cause);}};@Beanpublic RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory){RabbitTemplate rabbitTemplate=new RabbitTemplate();//设置连接工厂BeanrabbitTemplate.setConnectionFactory(connectionFactory);//手动开启rabbitTemplate.setMandatory(true);//设置传输数据是json格式rabbitTemplate.setMessageConverter(jsonMessageConverter());//流程:生产者-->交换机-->路由键-->队列//ConfirmCallback//流程:生产者-->交换机//1)成功 触发回调//2)失败 触发回调rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {log.info("ConfirmCallback,相关数据:{}", correlationData);log.info("ConfirmCallback,确认消息:{}", ack);log.info("ConfirmCallback,原因:{}", cause);}});//第二种方式//rabbitTemplate.setConfirmCallback(confirmCallback);//ReturnCallback:该回调函数的触发器与mandatory: true参数有必要关系//流程:交换机-->队列//成功 不触发回调//失败 触发回调rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {@Overridepublic void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {log.info("ReturnCallback,消息:{}", message);log.info("ReturnCallback,回应码:{}", replyCode);log.info("ReturnCallback,回应信息:{}", replyText);log.info("ReturnCallback,交换机:{}", exchange);log.info("ReturnCallback,路由键:{}", routingKey);}});return rabbitTemplate;}@Beanpublic Jackson2JsonMessageConverter jsonMessageConverter(){return new Jackson2JsonMessageConverter();}
}
3.消息监听指定具体的队列
import com.yl.controller.RabbitQueueReceiver;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author :jerry* @date :Created in 2021/12/29 13:11* @description:消费消息* @version: V1.1*/@Configuration
public class MessageListenerConfig {@Beanpublic SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory,RabbitQueueConfig rabbitQueueConfig,RabbitQueueReceiver rabbitQueuReceiver){SimpleMessageListenerContainer container=new SimpleMessageListenerContainer();container.setConnectionFactory(connectionFactory);//设置mq连接工厂对象container.setConcurrentConsumers(1);//设置并发消费者container.setMaxConcurrentConsumers(1);//设置最多的并发消费者container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认消息// container.setMessageConverter(jackson2JsonMessageConverter());//注意:此处不能使用Autowired根据类型自动注入队列,必须调用rabbitmqDirectConfig.firstQueue()获得,why?// 因为项目中可能存在多个队列,它们的类型都是Queue,自动注入会报错container.setQueues(rabbitQueueConfig.queue());container.setMessageListener(rabbitQueuReceiver);return container;}@Beanpublic Jackson2JsonMessageConverter jackson2JsonMessageConverter(){return new Jackson2JsonMessageConverter();}
}
4.消息生产者
import com.yl.common.Result;
import com.yl.common.SnowflakeIdWorker;
import com.yl.entity.Journal;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;/*** @author :jerry* @date :Created in 2021/12/29 11:11* @description:mq生产者* @version: V1.1*/@RestController
@Slf4j
public class SendController {final static SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);@Autowiredprivate RabbitTemplate rabbitTemplate;@RequestMapping("send")public Result send(){String exchange="rollback-exchange";String routingkey="rollback-routingkey";log.info("生产者开始发送消息");Journal journal = new Journal();journal.setId(idWorker.nextId());journal.setTitle("听闻广陵不知寒,大雪龙骑下江南");
// journal.setCreateTime(LocalDateTime.now());journal.setTitleDesc("怒发冲冠⑵,凭阑处⑶、潇潇雨歇⑷。抬望眼,仰天长啸⑸,壮怀激烈⑹。三十功名尘与土⑺,八千里路云和月⑻。莫等闲⑼、白了少年头,空悲切⑽。 靖康耻⑾,犹未雪。臣子恨,何时灭。驾长车,踏破贺兰山缺⑿。壮志饥餐胡虏肉⒀,笑谈渴饮匈奴血⒁。待从头、收拾旧山河,朝天阙⒂。");//注意:将消息推送到正常的交换机中//参数一:交换机名称//参数二:路由键//参数三:传递参数//流程:生产者-->交换机-->路由键-->队列rabbitTemplate.convertAndSend(exchange,routingkey,journal);log.info("生产者发送消息完成");return Result.succ("操作成功");}
}
5.消息的消费者
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener;
import org.springframework.stereotype.Component;/*** @author :jerry* @date :Created in 2021/12/29 11:31* @description:MQ消费者* @version: V1.1*/
@Slf4j
@Component
@RabbitListener(queues = {"rollback_queue"})
public class RabbitQueueReceiver extends AbstractAdaptableMessageListener {/*** 消息确认机制,消息不会重复消费* */@Overridepublic void onMessage(Message message, Channel channel) throws Exception {//消息的唯一ID,单调递增正整数,从1开始,当multiple=trues,一次性处理<=deliveryTag的所有long deliveryTag = message.getMessageProperties().getDeliveryTag();boolean multiple=false; //false单条 true 批量// channel.basicAck(deliveryTag, multiple); //正确消费消息
// channel.basicReject(deliveryTag,true); //为true会重新放回队列
// channel.basicNack(deliveryTag, multiple,true)try {String msg=new String(message.getBody(),"UTF-8");JSONObject json = JSONObject.parseObject(msg);Long id = json.getLong("id");log.info("消费的消息id"+id+"-------->>>>>>>"+"消费者消费消息的消息体:{}----->>>>>"+message);//睡眠四秒for(int i=0;i<4;i++){Thread.sleep(1000);System.out.println("...");}// if(deliveryTag%2==0){
// throw new RuntimeException("偶数必须为0");
// }log.info("消息已被正确消费--->>>>>>>>"+deliveryTag);//当前模式为单条消费channel.basicAck(deliveryTag, multiple);} catch (Exception e) {e.printStackTrace();//报异常重新投递channel.basicReject(deliveryTag,true);}}// @RabbitHandler
// public void handlerMessage(Journal orderVo) {
// log.info("消费者消费消息"+orderVo.toString());
// }
}
6.实体类对象
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;import java.time.LocalDateTime;/*** @author :jerry* @date :Created in 2021/12/29 14:37* @description:bean对象* @version: V1.1*/
@Data
public class Journal {private Long id;private String title;private String titleDesc;}
7.工具类
/*** Twitter_Snowflake<br>* SnowFlake的结构如下(每部分用-分开):<br>* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 -* 000000000000 <br>* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。* 41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>* 加起来刚好64位,为一个Long型。<br>* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,* SnowFlake每秒能够产生26万ID左右。*/
//雪花算法 生成主键ID
public class SnowflakeIdWorker {// ==============================Fields===========================================/** 开始时间截 (2015-01-01) */private final long twepoch = 1420041600000L;/** 机器id所占的位数 */private final long workerIdBits = 5L;/** 数据标识id所占的位数 */private final long datacenterIdBits = 5L;/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */private final long maxWorkerId = -1L ^ (-1L << workerIdBits);/** 支持的最大数据标识id,结果是31 */private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);/** 序列在id中占的位数 */private final long sequenceBits = 12L;/** 机器ID向左移12位 */private final long workerIdShift = sequenceBits;/** 数据标识id向左移17位(12+5) */private final long datacenterIdShift = sequenceBits + workerIdBits;/** 时间截向左移22位(5+5+12) */private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */private final long sequenceMask = -1L ^ (-1L << sequenceBits);/** 工作机器ID(0~31) */private long workerId;/** 数据中心ID(0~31) */private long datacenterId;/** 毫秒内序列(0~4095) */private long sequence = 0L;/** 上次生成ID的时间截 */private long lastTimestamp = -1L;// ==============================Constructors=====================================/*** 构造函数** @param workerId* 工作ID (0~31)* @param datacenterId* 数据中心ID (0~31)*/public SnowflakeIdWorker(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}// ==============================Methods==========================================/*** 获得下一个ID (该方法是线程安全的)** @return SnowflakeId*/public synchronized long nextId() {long timestamp = timeGen();// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}// 如果是同一时间生成的,则进行毫秒内序列if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;// 毫秒内序列溢出if (sequence == 0) {// 阻塞到下一个毫秒,获得新的时间戳timestamp = tilNextMillis(lastTimestamp);}}// 时间戳改变,毫秒内序列重置else {sequence = 0L;}// 上次生成ID的时间截lastTimestamp = timestamp;// 移位并通过或运算拼到一起组成64位的IDreturn ((timestamp - twepoch) << timestampLeftShift) //| (datacenterId << datacenterIdShift) //| (workerId << workerIdShift) //| sequence;}/*** 阻塞到下一个毫秒,直到获得新的时间戳** @param lastTimestamp* 上次生成ID的时间截* @return 当前时间戳*/protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}/*** 返回以毫秒为单位的当前时间** @return 当前时间(毫秒)*/protected long timeGen() {return System.currentTimeMillis();}// ==============================Test=============================================/** 测试 */public static void main(String[] args) {SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);for (int i = 0; i < 100; i++) {long id = idWorker.nextId();String insertSQL = "insert into orderNumber value('" + id + "');";System.out.println(insertSQL);}}
}
import lombok.Data;import java.io.Serializable;@Data
public class Result implements Serializable {private int code;private String msg;private Object data;public static Result succ(Object data) {return succ(200, "操作成功", data);}public static Result succ(int code, String msg, Object data) {Result r = new Result();r.setCode(code);r.setMsg(msg);r.setData(data);return r;}public static Result fail(String msg) {return fail(400, msg, null);}public static Result fail(int code, String msg, Object data) {Result r = new Result();r.setCode(code);r.setMsg(msg);r.setData(data);return r;}}
postmain调用接口生产消息:http://localhost:8084/send
结果: 项目地址:
RabbitMQ使用案例相关推荐
- SpringBoot整合rabbitmq使用案例
文章预览: 1 .环境准备 1.1添加依赖 1.2 配置yml 2.提供者发送消息 2.1 send 2.2 convertAndSend 3.消费者接收消息 3.1方式一 3.2方式二 案例源码 r ...
- RabbitMQ应用案例
一.创建一个maven工程. 二.引入依赖 <dependencies><!-- https://mvnrepository.com/artifact/com.rabbitmq/am ...
- 怎么看rabbitmq的浏览器信息_没用过消息队列?一文带你体验RabbitMQ收发消息
人生终将是场单人旅途,孤独之前是迷茫,孤独过后是成长. 楔子 先给大家说声抱歉,最近一周都没有发文,有一些比较要紧重要的事需要处理. 今天正好得空,本来说准备写SpringIOC相关的东西,但是发现想 ...
- java连接rabbitmq_没用过消息队列?一文带你体验RabbitMQ收发消息
楔子 先给大家说声抱歉,最近一周都没有发文,有一些比较要紧重要的事需要处理. 今天正好得空,本来说准备写SpringIOC相关的东西,但是发现想要梳理一遍,还是需要很多时间,所以我打算慢慢写,先把MQ ...
- Rabbitmq安装以及入门
8 RabbitMQ入门及安装 1 概述 官网:https://www.rabbitmq.com/ 什么是RabbitMQ,官方给出来这样的解释: RabbitMQ is the most widel ...
- RabbitMQ 学习笔记
RabbitMQ 学习笔记 RabbitMQ 学习笔记 1. 中间件 1.1 什么是中间件 1.2 为什么要使用消息中间件 1.3 中间件特点 1.4 在项目中什么时候使用中间件技术 2. 中间件技术 ...
- Java开发 - 消息队列之RabbitMQ初体验
目录 前言 RabbitMQ 什么是RabbitMQ RabbitMQ特点 安装启动 RabbitMQ和Kafka的消息收发区别 RabbitMQ使用案例 添加依赖 添加配置 创建RabbitMQ配置 ...
- RabbitMQ入门及笔记
RabbitMQ 文章目录 RabbitMQ 1. RabbitMQ的安装 2. RabbitMQ的相关概念 2.1 RabbitMQ的概念 2.2 四大核心概念 2.3 RabbitMQ 核心部分 ...
- RabbitMQ学习笔记(一)
前言: 学习B站UP主狂神说视频笔记整理视频链接 什么是中间件 中间件( Middleware ) 是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分.人们在使用中间件时,往往 ...
- RabbitMQ狂神说笔记(RabbitMQ B站狂神说笔记、KuangStudy、学相伴飞哥)
一. 引用文章 RabbitMQ狂神说笔记(B站狂神说笔记.KuangStudy.学相伴飞哥) RabbitMQ狂神说笔记(B站狂神说笔记.KuangStudy.学相伴飞哥)百度云盘地址,提取码:07 ...
最新文章
- Fedora 17 下安装codeblocks
- 【数据结构】二分查找
- char qt 转unicode_Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK 乱码与转码问题...
- 后处理编辑修改_Abaqus Python二次开发:内核脚本的快捷编辑方式
- 广度优先搜索(BFS)——马的遍历(洛谷 P1443)
- 拼多多被指洗钱 官方回应:将起诉“差评”并索赔1000万元
- 读取*.properties文件的配置信息
- 微信小程序MINA框架学习(零)
- vant组件做表格_有赞团队的vant ui组件库van-field使用
- 世界上最简单的会计书(资产负债表)
- centos7 firewall-cmd 命令报错 ModuleNotFoundError: No module named 'gi'
- 2020-08-15
- 企业IT管理岗的首选认证:ITIL®4 Foundation
- 计算机网络协议(五)——DNS、HTTPDNS
- 鲜为人知的Linux命令(3)
- 开箱即用的 SQL Server Docker
- 小米5x的android版本,小米5X是什么系统_小米5X系统更新-太平洋IT百科
- python数字切片_Python学习笔记-数字,列表,元祖,切片,循环
- 你的计划为什么执行不下去?怎么破?
- 2015 macbook air换第三方SSD(西数SN750)
热门文章
- 国资委定调联通电信前景:“共享竞合”的铁塔模式翻版
- 太阳直射点纬度计算公式_高中地理——每日讲1题(欧洲的气候、太阳高度角、日出时间)...
- 直播一小时营收破百万!虚拟主播说英文在B站疯狂吸金,背后企划公司IPO作价23亿...
- 怎么给表格加一列序号_如何给word表格添加一列序号?
- Inno Setup打包添加和去除管理员权限
- 科学计算机壁纸,科幻题材电脑插画桌面壁纸
- win10怎么在注册表中修改图片查看方式
- 南阳oj 58 bfs入门
- 醉枕江山第五十二章 公主中的公主
- 修改计算机用户名bat脚本