一、抽象消费类封装:
public abstract class Consumer {
protected final Logger logger = LoggerFactory.getLogger(getClass());
protected DefaultMQPushConsumer defaultMQPushConsumer;
@Value("${rocketMQ.nameServer.address}")
private String nameServerAddress;
@PostConstruct
private void init() throws MQClientException {
defaultMQPushConsumer = new DefaultMQPushConsumer();
defaultMQPushConsumer.setNamesrvAddr(nameServerAddress);
defaultMQPushConsumer.setConsumeThreadMax(20);
defaultMQPushConsumer.setConsumeThreadMin(10);
init(defaultMQPushConsumer);
}
private void init(DefaultMQPushConsumer defaultMQPushConsumer) throws MQClientException {
final MQConfig mqCfg = getMQConfig();
defaultMQPushConsumer.setInstanceName(mqCfg.getInstanceName());
defaultMQPushConsumer.setConsumerGroup(mqCfg.getConsumerGroup());
defaultMQPushConsumer.subscribe(mqCfg.getTopic(), mqCfg.getSubExpression());
// 设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费,如果非第一次启动,那么按照上次消费的位置继续消费
defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
defaultMQPushConsumer.setMessageModel(mqCfg.getMessageModel());// 设置为集群消费(区别于广播消费)
defaultMQPushConsumer.registerMessageListener(new MessageListenerConcurrently() { // 这里可以抽离出来,添加一个继承MessageListenerConcurrently的类
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
if (null != msgs && !msgs.isEmpty()) {
for (MessageExt msg : msgs) {
if (mqCfg.getTopic().equals(msg.getTopic())) {
try {
consume(msg, context);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} else {
// 如果没有return success, consumer会重新消费该消息, 直到return success
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
// 如果没有return success, consumer会重新消费该消息, 直到return success
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// Consumer对象在使用之前必须要调用start初始化, 初始化一次即可
defaultMQPushConsumer.start();
logger.info("///ConsumerGroup: {}, Topic: {}, SubExpression: {} started!", mqCfg.getConsumerGroup(), mqCfg.getTopic(), mqCfg.getSubExpression());
}
protected abstract void consume(MessageExt msg, ConsumeConcurrentlyContext context) throws Exception;
protected abstract MQConfig getMQConfig();
}
二、实际消费者示例:
@Component
public class ActualConsumer extends Consumer {
@Resource
private CustomService customService;
@Override
protected void consume(MessageExt msg, ConsumeConcurrentlyContext context) {
EntityDTO entityDTO = null;
try {
entityDTO = JSON.parseObject(new String(msg.getBody()), EntityDTO.class);
customService.doSomething(entityDTO);
} catch (Exception e) {
logger.error("doSomething fail, the body: {}", entityDTO == null ? null : entityDTO.toString());
}
}
@Override
protected MQConfig getMQConfig() {
return MQUtil.getMQConfig(CustomerMQCfg.CUSTOMER_PARAM.getGroup(), CustomerMQCfg.CUSTOMER_PARAM.getTopic());
}
}
三、工具类:
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
public class MQUtil {
public static MQConfig getMQConfig(String pushMessageGroup, String pushMessageTopic) {
MQConfig mqCfg = new MQConfig() {
@Override
public String getSubExpression() {
return "*";
}
@Override
public String getConsumerGroup() {
return pushMessageGroup;
}
@Override
public String getTopic() {
return pushMessageTopic;
}
@Override
public String getInstanceName() {
// 也可以使用UUID.randomUUID().toString(),如:return UUID.randomUUID().toString();
return String.valueOf(System.currentTimeMillis());
}
@Override
public MessageModel getMessageModel() {
return MessageModel.CLUSTERING;
}
};
return mqCfg;
}
}
四、配置类:
public enum CustomerMQCfg {
CUSTOMER_PARAM("CUSTOMER_GROUP", "CUSTOMER_TOPIC", "CUSTOMER_TAG", "自定义MQ配置信息"),
// 后续可以继续添加...;
LogParamMQCfg(String group, String topic, String tag, String remark) {
this.group = group;
this.topic = topic;
this.tag = tag;
this.remark = remark;
}
private String group;
private String topic;
private String tag;
private String remark;
@Override
public String getGroup() {
return group;
}
@Override
public void setGroup(String group) {
this.group = group;
}
@Override
public String getTopic() {
return topic;
}
@Override
public void setTopic(String topic) {
this.topic = topic;
}
@Override
public String getTag() {
return tag;
}
@Override
public void setTag(String tag) {
this.tag = tag;
}
@Override
public String getRemark() {
return remark;
}
@Override
public void setRemark(String remark) {
this.remark = remark;
}
}