前言
本文主要讲怎么应用rocketmq发送消息。
mq客户端核心类-DefaultMQProducer
核心方法
@Override
public SendResult send(Message msg) throws MQClientException, RemotingException, MQBrokerException,
InterruptedException {
return this.defaultMQProducerImpl.send(msg);
}
接口的各种发送消息的方法
默认实现类
类继承图
封装mq客户端的核心类
自己再封装一下,写个发送消息工具类,或者干脆搞到一个小的jar里去。
源码实现
package xxx.rocketmq;
import xxx.util.LogUtil;
import com.alibaba.rocketmq.client.exception.MQBrokerException;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.common.message.Message;
import com.alibaba.rocketmq.remoting.exception.RemotingException;
/**
* 生产者,初始化MQProducer
*/
public class Producer {
private String namesrvAddr; //ip
private String producerGroup; //group
private DefaultMQProducer producer; //官方自带默认实现
public String getNamesrvAddr() {
return namesrvAddr;
}
public void setNamesrvAddr(String namesrvAddr) {
this.namesrvAddr = namesrvAddr;
}
public String getProducerGroup() {
return producerGroup;
}
public void setProducerGroup(String producerGroup) {
this.producerGroup = producerGroup;
}
//初始化
public void init() {
LogUtil.INFOLOG.info("RocketMQ-Producer初始化参数开始");
LogUtil.INFOLOG.info("producerGroup: " + producerGroup);
producer = new DefaultMQProducer(producerGroup);
producer.setNamesrvAddr(namesrvAddr);
// 定义实例名称,不适用默认.
producer.setInstanceName(Long.toString(System.currentTimeMillis()));
// Message Body大小超过阀值,则压缩,默认是1024 * 4
producer.setCompressMsgBodyOverHowmuch(Integer.MAX_VALUE);
try {
//启动生产者
producer.start();
} catch (Exception e) {
LogUtil.INFOLOG.error("RocketMQ-Producer初始化参数异常:", e);
}
}
public void destroy() {
producer.shutdown();
}
/**
* 发送消息
*
* @param message
* @return
*/
public SendResult send(Message message) throws InterruptedException,
RemotingException, MQClientException, MQBrokerException {
//调用官方默认实现发送消息
SendResult result = producer.send(message);
return result;
}
}
定义bean
<!-- 扫码 -->
<bean id="mqProducer_xxx" class="xxx.rocketmq.Producer" init-method="init" destroy-method="destroy">
<property name="namesrvAddr" value="${namesrvAddr}"/>
<property name="producerGroup" value="${rocketmq.xxx.group}"/>
</bean>
应用层
应用层工具类
应用项目里再简单封装一下,加了topic功能。
定义bean
<bean id="sendMqProcess_xxx" class="xxx.trade.process.SendMqProcess">
<property name="producer" ref="mqProducer_xxx"/>
<property name="topic" value="${rocketmq.xxx.topic}"/>
<property name="subExpression" value="${rocketmq.xxx.subExpression}"/>
</bean>
源码实现
package xxx.trade.process;
import xxx.core.exception.BizException;
import xxx.rocketmq.Producer;
import xxx.trade.constant.xxxReturnCode;
import xxx.trade.util.LogUtil;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.client.producer.SendStatus;
import com.alibaba.rocketmq.common.message.Message;
public class SendMqProcess {
private Producer producer;
private String topic;
private String subExpression;
/**
* 发送mq消息
*
* @param jsonMsgContent
* 消息内容,必须是json格式
* @return
* @throws BizException
* @see
*/
public SendStatus sendMqMessage(String jsonMsgContent) throws BizException {
try {
Message msg = new Message(topic, subExpression,
(jsonMsgContent).getBytes("UTF-8"));
SendResult sendResult = producer.send(msg);
LogUtil.INFOLOG.info("消息内容:" + jsonMsgContent + "\n返回结果:"
+ sendResult.toString());
return sendResult.getSendStatus();
} catch (Exception e) {
throw new BizException(xxxReturnCode.DEAL_EXCEPTION.getCode(),
xxxReturnCode.DEAL_EXCEPTION
.getDesc("Producer send message 异常:"
+ jsonMsgContent)
+ e);
}
}
public void setProducer(Producer producer) {
this.producer = producer;
}
public void setTopic(String topic) {
this.topic = topic;
}
public void setSubExpression(String subExpression) {
this.subExpression = subExpression;
}
}
应用层提供静态方法发送消息
提供类的静态方法,方便使用。
public class xxxMerchantNotifyManager {
private static final SendMqProcess SENDMQPROCESS_xxx = (SendMqProcess) SpringContext
.getService("sendMqProcess_xxx");
// 异步线程发送消息到MQ
public static void sendMqMessage(final BackMethodParm backMethodParm,
final Orderbill orderbill, final boolean ignore) {
Runnable childThread = new Runnable() {
@Override
public void run() {
boolean isSentOk = false;
String xxx = orderbill.getxxx();
try {
// 参数处理
String json = convertJSONString(backMethodParm, ignore);
try {
// 发送消息队列
LogUtil.INFOLOG.info("sendMqMessage消息内容:" + json);
SendStatus state = SENDMQPROCESS_QRCODE
.sendMqMessage(json);
LogUtil.INFOLOG.info("sendMqMessage返回内容:" + state.toString());
if (state == SendStatus.SEND_OK
|| state == SendStatus.FLUSH_DISK_TIMEOUT
|| state == SendStatus.FLUSH_SLAVE_TIMEOUT
|| state == SendStatus.SLAVE_NOT_AVAILABLE) {
isSentOk = true;
}
} catch (BizException e) {
log.error(LogConst.THROWABLEEXCEPTIONS + xxx
+ "异步通知发送异常", e);
} catch (Exception e) {
log.error(LogConst.THROWABLEEXCEPTIONS + xxx
+ "异步通知发送异常", e);
}
} catch (Exception ex) {
log.error(LogConst.THROWABLEEXCEPTIONS + xxx
+ "异步通知发送json转对象发生异常", ex);
}
// MQ发送失败进入容错处理
if (!isSentOk) {
try {
NotifyFault entity = content2NotifyFault(orderbill,
backMethodParm);
log.info(LogConst.THROWABLEEXCEPTIONS + xxx
+ "异步通知发送:" + entity);
ServiceDeclare.notifyFaultService
.insertNotifyFault(entity);
} catch (Exception e) {
log.error(LogConst.THROWABLEEXCEPTIONS + xxx
+ "异步通知消息转容错处理发生异常", e);
}
}
}
};
try {
threadPool.execute(childThread);
} catch (Throwable t) {
log.error(LogConst.THROWABLEEXCEPTIONS + "mq消息处理异常:", t);
}
}
调用静态方法发送消息
xxxMerchantNotifyManager.sendMqMessage();
总结
大致的思路就是,基于mq客户端官方自带的默认实现去发送消息,然后自己也可以封装一下,甚至可以封装多层,每一层的封装,其实就是对于特殊情况多加了一点内容。如果是测试使用,其实直接调用官方默认实现发送消息即可。只不过生产环境,一般都会封装一层,甚至多层。