最近项目中需要使用的小工具,牵扯到后台需要前后台做消息通信,和web端同事简单比较了下,决定使用MQ
进行通讯,之前App项目中使用MQTT
比较多,对于Rabbitmq
只是简单的知道是一个后台经常用到的异步操作队列,当然既然要用,咱也不虚,简单了解了下,很快实现了功能,用起来挺方便的,这里简单作一下笔记。望后端大佬勿喷!~
MQ文档地址: https://www.rabbitmq.com/tutorials/tutorial-one-java.html
Android项目中引入Rabbitmq
引入项目还是比较简单的,直接在maven repository
中搜索一下Rabbitmq
,之后找到gradle
依赖方式,copy过来即可。
implementation 'com.rabbitmq:amqp-client:5.12.0'
初始化Rabbitmq
//初始化ConnectionFactory对象
private val mConnectFactory by lazy { ConnectionFactory() }
//设置需要使用到的参数
mConnectFactory.apply {
virtualHost = mqVhost
//主机地址
host = mqHostname
//端口号
port = mqPort
//用户名
username = mqUsername
//密码
password = mqPassword
//设置连接恢复
isAutomaticRecoveryEnabled = true
}
至此简单的初始化就完成了
接收消息
//订阅消息
fun subscribe() {
//这里创建一个线程,MessageReceiverTask其实就是一个Runnable
MessageReceiverTask(mConnectFactory).apply{
Thread(this).start()
}
}
接下来就是重头戏,关于MessageReceiverTask
实现。
... 省略Runnable实现
override fun run() {
val connection = connectFactory.newConnection()
val channel = connection.createChannel()
//设置处理完一个消息,再接口下一个消息
channel.basicQos(1)
//声明交换机类型
channel.exchangeDeclare(mqChannelName, "fanout", true)
//声明队列
channel.queueDeclare(mqMessageQueueName, true, false, false, null)
//根据路由键将队列绑定到交换机上
channel.queueBind(mqMessageQueueName, mqChannelName, mqRoutingKey)
//创建消费者
val consumer = object : DefaultConsumer(channel) {
override fun handleDelivery(
consumerTag: String?,
envelope: Envelope,
properties: AMQP.BasicProperties?,
body: ByteArray?
) {
if (body == null) {
Log.e("info", "收到消息-body为空")
//如果接收到的消息体为空,则表示消息没有用,直接拒绝
//这里false表示只处理当前消息
channel.basicReject(envelope.deliveryTag, false)
} else {
...省略若干业务
//处理完业务逻辑之后,通知消息队列该消息已经被消费
channel.basicAck(envelope.deliveryTag, false)
}
}
}
//启动一个消费者,该方法会返回消费者的标识符
//这里设置false表示使用手动确认消费,如果设置为true,则会自动确认
channel.basicConsume(mqMessageQueueName, false, consumer)
}
至此就可以愉快的玩耍了。
对于发送其他本质上是一样的,由于我操作只关心接口,如果没有写代码。这里列一下发现的方法,可以自行查阅下文档了解更多。
MQ文档地址: https://www.rabbitmq.com/tutorials/tutorial-one-java.html
发送消息
...其他部分与接收相同
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());