消息生产者p将消息放入队列
消费者监听队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列删除
(隐患,消息可能没有被消费者正确处理,已经消失了,无法恢复)
应用场景:聊天室
案例:
1>.首先准备依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2>.写一个test类
public class SimpleTest {
//模拟生产者将消息放入队列
@Test
public void send() throws Exception{
/*1 创建连接工厂
* 2 配置共创config
* 3 获取连接
* 4获取信道
* 5 从信道声明queue
* 6 发送消息
* 7 释放资源
*/
ConnectionFactory factory=new ConnectionFactory();
factory.setHost("106.23.34.56");
factory.setPort(5672);
factory.setVirtualHost("/tb");
factory.setUsername("admin");
factory.setPassword("123456");
//从工厂获取连接
Connection conn=factory.newConnection();
//从连接获取信道
Channel chan=conn.createChannel();
//利用channel声明第一个队列
chan.queueDeclare("simple", false, false, false, null);
//queue String类型,表示声明的queue对列的名字
//durable Boolean类型,表示是否持久化
//exclusive Boolean类型:当前声明的queue是否专注;true当前连接创建的
//任何channle都可以连接这个queue,false,新的channel不可使用
//autoDelete Boolean类型:在最后连接使用完成后,是否删除队列,false
//arguments Map类型,其他声明参数
//发送消息
String msg="helloworld,nihaoa";
chan.basicPublish("", "simple", null, msg.getBytes());
//exchange String类型,交换机名称,简单模式使用默认交换""
//routingkey String类型,当前的消息绑定的routingkey,简单模式下,与队列同名即可
//props BasicProperties类型,消息的属性字段对象,例如BasicProperties
//可以设置一个deliveryMode的值0 持久化,1 表示不持久化,durable配合使用
//body byte[] :消息字符串的byte数组
}
//模拟消费端
@Test
public void receive() throws Exception{
ConnectionFactory factory=new ConnectionFactory();
factory.setHost("106.23.34.56");
factory.setPort(5672);
factory.setVirtualHost("/tb");
factory.setUsername("admin");
factory.setPassword("123456");
//从工厂获取连接
Connection conn=factory.newConnection();//从连接获取信道Channel chan=conn.createChannel();chan.queueDeclare("simple", false, false, false, null);//创建一个消费者QueueingConsumer consumer= new QueueingConsumer(chan);chan.basicConsume("simple", consumer);//监听队列while(true){//获取下一个delivery,delivery从队列获取消息Delivery delivery = consumer.nextDelivery();String msg=new String(delivery.getBody());System.out.println(msg);}}}
生产者将消息放入队列
多个消费者同时监听同一个队列,消息如何被消费?
C1,C2共同争抢当前消息队列的内容,谁先拿到消息,谁来负责消费
应用场景:红包;大型项目中的资源调度过程(直接由最空闲的系统争抢到资源处理任务)
案例:
1>首先写一个工具类
public class ConnectionUtil {
public static Connection getConn(){
try{
ConnectionFactory factory=new ConnectionFactory();
factory.setHost("106.33.44.179");
factory.setPort(5672);
factory.setVirtualHost("/tb");
factory.setUsername("admin");
factory.setPassword("123456");
//从工厂获取连接
Connection conn=factory.newConnection();
return conn;
}catch(Exception e){
System.out.println(e.getMessage());
return null;
}
}
}
2>写test类
public class WorkTest {
@Test
public void send() throws Exception{
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明队列
chan.queueDeclare("work", false, false, false, null);
for(int i=0;i<100;i++){
String msg="1712,hello:"+i+"message";
chan.basicPublish("", "work", null, msg.getBytes());
System.out.println("第"+i+"条信息已经发送");
}
chan.close();
conn.close();
}
@Test
public void receive1() throws Exception{
//获取连接,获取信道
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
chan.queueDeclare("work", false, false, false, null);
//同一时刻服务器只发送一条消息给同一消费者,消费者空闲,才发送一条
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//绑定队列和消费者的关系
//queue
//autoAck:消息被消费后,是否自动确认回执,如果false,不自动需要手动在
//完成消息消费后进行回执确认,channel.ack,channel.nack
//callback
//chan.basicConsume(queue, autoAck, callback)
chan.basicConsume("work", false, consumer);
//监听
while(true){
Delivery delivery=consumer.nextDelivery();
byte[] result = delivery.getBody();
String msg=new String(result);
System.out.println("接受到:"+msg);
Thread.sleep(50);
//返回服务器,回执
chan.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
@Test
public void receive2() throws Exception{
//获取连接,获取信道
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
chan.queueDeclare("work", false, false, false, null);
//同一时刻服务器只发送一条消息给同一消费者,消费者空闲,才发送一条
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//绑定队列和消费者的关系
//queue
//autoAck:消息被消费后,是否自动确认回执,如果false,不自动需要手动在
//完成消息消费后进行回执确认,channel.ack,channel.nack
//callback
//chan.basicConsume(queue, autoAck, callback)
chan.basicConsume("work", false, consumer);
//监听
while(true){
Delivery delivery=consumer.nextDelivery();
byte[] result = delivery.getBody();
String msg=new String(result);
System.out.println("接受到:"+msg);
Thread.sleep(150);
//返回服务器,回执
chan.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
生产者将消息交给交换机
有交换机根据发布订阅的模式设定将消息同步到所有的绑定队列中;
后端的消费者都能拿到消息
应用场景:邮件群发,群聊天,广告
案例:
public class FanoutTest {
//交换机,有类型,发布订阅:fanout
//路由模式:direct
//主题模式:topic
@Test
public void send() throws Exception {
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明交换机
//参数意义,1 交换机名称,2 类型:fanout,direct,topic
chan.exchangeDeclare("fanoutEx", "fanout");
//发送消息
for(int i=0;i<100;i++){
String msg="1712 hello:"+i+"msg";
chan.basicPublish("fanoutEx", "", null, msg.getBytes());
System.out.println("第"+i+"条信息已经发送");
}
}
@Test
public void receiv01() throws Exception{
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//生命队列
chan.queueDeclare("fanout01", false, false, false, null);
//声明交换机
chan.exchangeDeclare("fanoutEx", "fanout");
//绑定队列到交换机
//参数 1 队列名称,2 交换机名称 3 路由key
chan.queueBind("fanout01", "fanoutEx", "");
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//消费者与队列绑定
chan.basicConsume("fanout01",false, consumer);
while(true){
Delivery delivery= consumer.nextDelivery();
System.out.println("一号消费者接收到"+
new String(delivery.getBody()));
chan.basicAck(delivery.getEnvelope().
getDeliveryTag(), false);
}
}
@Test
public void receiv02() throws Exception{
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//生命队列
chan.queueDeclare("fanout02", false, false, false, null);
//声明交换机
chan.exchangeDeclare("fanoutEx", "fanout");
//绑定队列到交换机
//参数 1 队列名称,2 交换机名称 3 路由key
chan.queueBind("fanout02", "fanoutEx", "");
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//消费者与队列绑定
chan.basicConsume("fanout02",false, consumer);
while(true){
Delivery delivery= consumer.nextDelivery();
System.out.println("二号消费者接收到"+new String(delivery.getBody()));
chan.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
生产者发送消息到交换机,同时绑定一个路由Key,交换机根据路由key对下游绑定的队列进行路
由key的判断,满足路由key的队列才会接收到消息,消费者消费消息
应用场景: 项目中的error报错
案例:
public class RoutingTopicTest {
@Test
public void routingSend() throws Exception{
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明交换机
//参数意义,1 交换机名称,2 类型:fanout,direct,topic
chan.exchangeDeclare("directEx", "direct");
//发送消息
String msg="路由模式的消息";
chan.basicPublish("directEx", "jt1713",
null, msg.getBytes());
}
@Test
public void routingRec01() throws Exception{
System.out.println("一号消费者等待接收消息");
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明队列
chan.queueDeclare("direct01", false, false, false, null);
//声明交换机
chan.exchangeDeclare("directEx", "direct");
//绑定队列到交换机
//参数 1 队列名称,2 交换机名称 3 路由key
chan.queueBind("direct01", "directEx", "jt1712");
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//消费者与队列绑定
chan.basicConsume("direct01",false, consumer);
while(true){
Delivery delivery= consumer.nextDelivery();
System.out.println("一号消费者接收到"+
new String(delivery.getBody()));
chan.basicAck(delivery.getEnvelope().
getDeliveryTag(), false);
}
}
@Test
public void routingRec02() throws Exception{
System.out.println("二号消费者等待接收消息");
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明队列
chan.queueDeclare("direct02", false, false, false, null);
//声明交换机
chan.exchangeDeclare("directEx", "direct");
//绑定队列到交换机
//参数 1 队列名称,2 交换机名称 3 路由key
chan.queueBind("direct02", "directEx", "jt1711");
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//消费者与队列绑定
chan.basicConsume("direct02",false, consumer);
while(true){
Delivery delivery= consumer.nextDelivery();
System.out.println("二号消费者接收到"+
new String(delivery.getBody()));
chan.basicAck(delivery.getEnvelope().
getDeliveryTag(), false);
}
}
}
*号代表单个词语
#代表多个词语
其他的内容与routing路由模式一致
案例:
public class RoutingTopicTest {
@Test
public void routingRec02() throws Exception{
System.out.println("二号消费者等待接收消息");
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明队列
chan.queueDeclare("direct02", false, false, false, null);
//声明交换机
chan.exchangeDeclare("directEx", "direct");
//绑定队列到交换机
//参数 1 队列名称,2 交换机名称 3 路由key
chan.queueBind("direct02", "directEx", "jt1711");
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//消费者与队列绑定
chan.basicConsume("direct02",false, consumer);
while(true){
Delivery delivery= consumer.nextDelivery();
System.out.println("二号消费者接收到"+
new String(delivery.getBody()));
chan.basicAck(delivery.getEnvelope().
getDeliveryTag(), false);
}
}
@Test
public void topicSend() throws Exception{
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明交换机
//参数意义,1 交换机名称,2 类型:fanout,direct,topic
chan.exchangeDeclare("topicEx", "topic");
//发送消息
String msg="主题模式的消息";
chan.basicPublish("topicEx", "jt1712.add.update",
null, msg.getBytes());
}
@Test
public void topicRec01() throws Exception{
System.out.println("一号消费者等待接收消息");
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明队列
chan.queueDeclare("topic01", false, false, false, null);
//声明交换机
chan.exchangeDeclare("topicEx", "topic");
//绑定队列到交换机
//参数 1 队列名称,2 交换机名称 3 路由key
chan.queueBind("topic01", "topicEx", "jt1712");
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//消费者与队列绑定
chan.basicConsume("topic01",false, consumer);
while(true){
Delivery delivery= consumer.nextDelivery();
System.out.println("一号消费者接收到"+
new String(delivery.getBody()));
chan.basicAck(delivery.getEnvelope().
getDeliveryTag(), false);
}
}
@Test
public void topicRec02() throws Exception{
System.out.println("二号消费者等待接收消息");
//获取连接
Connection conn = ConnectionUtil.getConn();
Channel chan = conn.createChannel();
//声明队列
chan.queueDeclare("topic02", false, false, false, null);
//声明交换机
chan.exchangeDeclare("topicEx", "topic");
//绑定队列到交换机
//参数 1 队列名称,2 交换机名称 3 路由key
chan.queueBind("topic02", "topicEx", "jt1712.#");
chan.basicQos(1);
//定义消费者
QueueingConsumer consumer=new QueueingConsumer(chan);
//消费者与队列绑定
chan.basicConsume("topic02",false, consumer);
while(true){
Delivery delivery= consumer.nextDelivery();
System.out.println("二号消费者接收到"+
new String(delivery.getBody()));
chan.basicAck(delivery.getEnvelope().
getDeliveryTag(), false);
}
}
}
文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr
文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc
文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8
文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束
文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求
文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname
文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include<stdio.h>#include<string.h>#include<stdlib.h>#include<malloc.h>#include<iostream>#include<stack>#include<queue>using namespace std;typed_二叉树的建立
文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码
文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词
文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限
文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定
文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland