三.RabbitMQ客户端开发

1.链接RabbitMQ:

//链接rabbitmq有下面两种方式

//1.设置参数方式
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername(...);
factory.setPassword(...)
factory.setHost(...);
factory..setPort(...);
Connection conn = factory.new Connection();


//2.uri方式
ConnectionFactory factory = new ConnectionFactory();
factory.setUri("amqp://userName:password@ipAddress:port/virtualHost");

在高并发环境下使用rabbitmq时,如果每一个线程创建一个connection,会非常消耗资源(因为创建tcp链接是非常耗时的)

所以rabbitmq采用了nio的connection复用技术,使用channel来进行数据交互

也就是每一个线程共享一个connection,然后为每一个线程创建一个channel

2、使用交换器和队列

交换器和队列是AMQP中high-level层面的构建模块,在使用它们的时候应该确保它们已经存在了,所以在使用前应该先声明

声明一个队列和交换器

String exchangeName = "oneExchange";
//声明交换器
channel.exchangeDeclare(exchangeName,"direct",true);
//队列名称由rabbitmq自动生成
String queueName = channel.queueDeclare().getQueue();
/*
也可以这样手动声明队列
channel.queueDeclare(queueName.true,false,false,null);
*/
String rountingKey = "key";
//绑定队列和交换器
channel.queueBind(queueName,exchangeName,rountingKey);

上述声明的交换器和队列都是connection层面的,也就是其他的channel也可以使用

当然可以设置创建队列的相关参数来声明一个应用层面的队列

exchangeDeclare方法详解

/*
1.这个方法的返回值是DeclareOk ,用来标识已经成功声明了一个交换器
2、@param:
	exchange:交换器的名称
	type:交换器的类型 
	durable:是否消息持久化(如果为true,在服务器重启的时候不会丢失相关信息)
	autoDelete:自动删除的前提是至少有一个队列或者交换器与这个交换器绑定
			   之后所有与这个交换器绑定的队列或者交换器都与自己解绑
			   (注意:不能单纯的理解为connection断开时,会自动删除本交换器)
	internal:设置是否内置。如果是true,表示是内置的交换器,客户端无法直接将消息发送到这个交换器上,
			  而是必须由其他交换器将消息路由到这个交换器上
	argument:其他的一些结构化的参数
*/
Exchange.DeclareOk ExchangeDeclare(String exchange,
					String type,boolean durable,
					boolean autoDelete,boolean internal,						
					Map<String,Object> arguments
)

/*
	这个方法比前面的相当于在MQ的命令中多设置了一个nowait参数
	上面的构造器需要等待服务器返回DeclareOk对象才可以继续向下执行
	而这个方法不需要服务器返回任何东西
*/
void ExchangeDeclare(String exchange,
					String type,boolean durable,
					boolean autoDelete,boolean internal,						
					Map<String,Object> arguments
)

/*
	判断交换器是否存在
*/

Exchange.DeclareOk exchangeDeclarePassive(String exchangeName)
				
)

/*
	删除交换器
*/
Exchange.DeclareOk exchangeDelete(String exchangeName,boolean isUnused)


queueDeclare详解

//声明队列只有如下两个重载的方法
/*
	不带任何参数的queueDeclare方法默认创建一个由rabbitmq命名的、排他的、自动删除的、非持久化的队列
*/
Queue.DeclareOk queueDeclare()
/*
	@param:
		queueName:队列名称
		durable:是否持久化
		exclisive:是否排外的,有两个作用:
			一:当连接关闭时connection.close()该队列是否会自动删除;
			二:该队列是否是私有的private:
					如果不是排外的,可以使用两个消费者都访问同一个队列,没有任何问题,
			    	如果是排外的,会对当前队列加锁,其他通道channel是不能访问的,如果强制访问会报异常:
		autoDelete:是否自动删除(类似exchange)
		arguments:一些其他结构化参数

*/			
Queue.DeclareOk queueDeclare(String queueName,boolean durable,boolean exclusive,
							boolean autoDelete,Map<String,Object> arguments)



/*
	删除队列
*/
Queue.DeleteOk queueDelete(String queue,boolean ifUnserd,boolean ifEmpty)

void queueDeleteNoWait(String queue,boolean ifUnsed,boolean ifEmpty)
/*
	清空队列,但是不删除队列
*/

Queue.PurgeOk queuePurge(String queue)

queueBind详解

/*
	使用BindingKey来绑定队列和交换器
*/
Queue.BindOk queueBind(String queueName,String exchangeName,String rountingKey)

Queue.BindOk queueBind(String queueName,String exchangeName,String rountingKey,Map<String,Object> arguments)

void queueBindNoWait(String queueName,String exchangeName,String rountingKey,Map<String,Object> arguments)

/*
	解绑
*/
Queue.UnbindOk queueUnbind(String queueName,String exchangeName,String rountingKey)

Queue.UnbindOk queueUnbind(String queueName,String exchangeName,String rountingKey,Map<String,Object> arguments)



/*
	交换器与交换器绑定
*/
Exchange.BindOk exchangeBind(String destination,String source,String rountingKey)

Exchange.BindOk exchangeBind(String destination,String source,String rountingKey,Map<String,Object> arguments)

void exchangeBindNoWait(String destination,String source,String rountingKey,Map<String,Object> arguments)

3.发送消息

//如果要发送一条消息,可以使用下列方法
String message = "hello rabbitmq";
channel.basicPublish(exchangeName,rountingKey,null,message.getBytes());

/*
	basicPublish方法参数说明
	@param:
		String exchangeName:交换器名称,指名消息要发到哪个交换器上
		String rountingKey:路由键
		BasicProperties props:消息的基本属性集
		byte[] body:消息体
		immediate:下一章进行描述
*/
void basicPublish(String exchangeName,String rountingKey,boolean mandatory,boolean immediate,
					BasicProperties properties,byte[] body)

4.消费消息:

rabbitmq的消费模式有两种:推push和拉pull

/*
推模式使用Basic.Consume进行消费--->持续订阅(while循环)
拉模式使用Basic.Get进行消费--->消费单条消息
*/


/*
	推模式消费信息,持续订阅
	与此模式相关的有两个类:Consumer和DefaultConsumer
	可以通过实现Consumer接口或者继承DefaultConsumer来实现
*/

//设置不自动提交,在接受到消息后进行显示的ack提交,可以放置消息丢失
boolean autoAck = false;
channel.basicQos(64);
//myConsumerTag用来区分多个消费者
//这个方法有多个重载的方法,还有一个boolean参数表示是否可以将同一个conn的生产者的消息发送给这个conn的消费者(true表示不能)
channel.basicConsumer(queueName,autoAck,"myConsumerTag",new DefaultConsumer(channel){
	//重写回调函数的逻辑
	//这个callback方法会分配到与channel相关的的线程池上,不存在线程安全问题
	@Override
	public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body){
		String rountingKey = envelop.getRountingKey();
		String contentType = properties.getContentType();
		long deliveryTag = envelope.getDeliveryTag();
		channel.basicAck(deliveryTag,false);
		
	}
	/*
		还有很多可以重写的方法
		handleShutDownSignal方法:当conn或者channel关闭的时候会调用这个方法
	*/

});




/*
	拉模式消费方式
	只有下面一个方法,没有重载方法
*/
GetResponse basicGet(String queueName,boolean autoAck)

/*
	拉模式的关键代码
*/

GetResponse response = channel.basicGet(queueName,false);
String result = response.getBody()
channel.basicAck(response.getEnvelope().getDeliveryTag(),false);

5.消费端的确认与拒绝

RabbitMQ的消息确认机制:

1.如果autoAck为false,rabbitmq会等待消费者显式地回复确认信号后才将消息从磁盘或者内存中移除,实质上是先打上删除标记,当收到确认信号后再将消息删除
2.如果autoAck为true,rabbitmq会自动把发送出去的消息置为确认,然后从磁盘或者内存中删除,而不管消费者是否已经接受刅了消息
3.如果消费者还未确认消息,然后断开了连接,rabbitmq会将该消息重新放入队列中进行消费,等待投递给下一个消费者
4.rabbitmq没有过期时间这一概念

拒绝消息:

/*
	拒绝一条消息
	@param:
		deliveryTag:消息的编号,是一个64位的长整型值
		requeue:如果设为true,则会将此条消息重新加入队列进行二次消费,如果false,会直接丢弃该条消息
*/
void basicReject(long deliveryTag,boolean requeue)


/*
	批量拒绝消息
	如果multiple为false,则只拒绝deliveryTag这一条消息
	如果multiple为true,则拒绝deliveryTag之前的所有消息
*/
void basicNack(long deliveryTag,boolean multiple,boolean requeue)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值