通过代码逐行分析api含义
生产者代码
/**
* 生产者
*/
public class RabbitProduct {
public static void main(String[] args) throws IOException, TimeoutException {
//连接工厂
ConnectionFactory factory =new ConnectionFactory();
factory.setHost(GlobalConstants.localhost);
factory.setPort(GlobalConstants.port);
factory.setHandshakeTimeout(GlobalConstants.timeOut);//设置个超时时间,不然立马报连接超时
factory.setUsername("root");
factory.setPassword("root");
//创建连接
Connection connection=factory.newConnection();
//创建频道
Channel channel=connection.createChannel();
//创建一个type为direct,持久化的,非自动删除的交换器
channel.exchangeDeclare(GlobalConstants.EXCHANGE_NAME,"direct",true,false,null);
//创建一个持久化,非排他,非自动删除的队列
channel.queueDeclare(GlobalConstants.QUEUE_NAME,true,false,false,null);
//交换器与队列通过路由键绑定
channel.queueBind(GlobalConstants.QUEUE_NAME,GlobalConstants.EXCHANGE_NAME,GlobalConstants.ROUTING_KEY);
String msg="hello wrx!";
//发送消息到队列中
channel.basicPublish(GlobalConstants.EXCHANGE_NAME,GlobalConstants.ROUTING_KEY, MessageProperties.PERSISTENT_TEXT_PLAIN,msg.getBytes("UTF-8"));
System.out.println("send msg->>>>"+msg);
/**
* 设置投递模式delivery mode为2,消息会持久化到服务器中
* 设置优先级priority为1
*/
String msg2="hello delivery!";
channel.basicPublish(GlobalConstants.EXCHANGE_NAME,
GlobalConstants.ROUTING_KEY,
new AMQP.BasicProperties.Builder().contentType("text/plain").deliveryMode(2).priority(1).build()
,msg2.getBytes("UTF-8"));
System.out.println("send msg->>>>" + msg2);
/**
* 带headers的信息
*/
String msg3="hello headers!";
Map<String,Object> headers =new HashMap<String,Object>();
headers.put("location","company");
headers.put("time","now");
channel.basicPublish(GlobalConstants.EXCHANGE_NAME,
GlobalConstants.ROUTING_KEY,
new AMQP.BasicProperties.Builder().headers(headers).build(),
msg3.getBytes("UTF-8"));
System.out.println("send msg->>>>" + msg3);
/**
* 带过期时间的信息
*/
String msg4="hello expiration!";
channel.basicPublish(GlobalConstants.EXCHANGE_NAME,
GlobalConstants.ROUTING_KEY,
new AMQP.BasicProperties.Builder().expiration("60000").build(),
msg4.getBytes("UTF-8"));
System.out.println("send msg->>>>" + msg4);
//关闭频道和连接
channel.close();
connection.close();
}
}
连接RabbitMq
ConnectionFactory factory =new ConnectionFactory();
factory.setHost(GlobalConstants.localhost);
factory.setPort(GlobalConstants.port);
factory.setHandshakeTimeout(GlobalConstants.timeOut);//设置个超时时间,不然立马报连接超时
factory.setUsername("root");
factory.setPassword("root");
//创建连接
Connection connection=factory.newConnection();
//创建频道
Channel channel=connection.createChannel();
setHandshakeTimeout翻译为连接握手超时时间,默认为10000ms,根据当前网络和使用情况可以酌情修改
除了每个参数设值的连接创建方式,还有设置uri的形式:
factory.setUril("amqp:lluserName:password@ipAddress:portNumber/virtualHost")
注意要点
Connection可以创建多个channel实例,但是channel实例不能在多线程间共享。某些情况下channel操作可以并发运行,但是在其他情况下会导致在网络上出现错误的通信帧交错,也会影响发送方确认机制的运行,多线程共享channel实例是非线程安全
exchangeDeclare参数说明
exchange:交换器名称
type:交换器类型,常见fanout direct topic
durable:是否持久化 持久化在服务器重启时不会丢失相关信息
autoDelte:是否自动删除 自动删除的前提是至少有一个队列或者交换器与这个交换器绑定,之后所有与这个交换器绑定的队列或者交换器都与此解绑。注意!不能错误的理解为:当与此交换器连接的客户端都断开时,RabbitMQ会自动删除本交换器
internal:“是否内置,如果设置成内置交换器,客户端程序无法直接发送消息到这个交换器中,只能通过交换器路由到交换器这种方式
argument:其他一些结构化参数,如alternate-exchange
queueDeclare参数说明
queue:队列的名称
durable:是否持久化
exclusive:是否排他,如果一个队列声明为排他队列,该队列仅首次声明它的连接可见,并在连接断开时自动删除。
- 排他队列是基于连接可见的,同一个连接的不同信道是可以同时访问同一连接创建的排他队列
- “首次”是指如果一个连接已经声明了一个排他队列,其他连接是不允许建立同名的排他队列的,这与普通队列不同
- 即使队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除,这种队列适用于一个客户端同时发送和读取消息的应用场景
autodelete:是否自动删除,自动删除的前提是:至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。不能错误的理解为:当连接到此队列的所有客户端断开就自动删除
arguments:一些其他参数
queueBind参数说明
queue:队列名称
exchange:交换器名称
routingKey:绑定队列和交换器的路由键
argument:定义绑定的一些参数
basicPublish参数说明
exchange:交换器名称
routingKey:绑定队列和交换器的路由键
props:其他参数的包装类,可以使用new AMQP.BasicProperties.Builder方式创建带headers的和带过期时间(expexpiration)的消息
body:消息本体