java使用rocketMQ

3、java使用rocketMQ

Pom文件添加

<!--begin rocketMq -->
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.2.0</version>
</dependency>
<!--end rocketMq -->
<!-- 導入配置文件處理器,配置文件進行綁定就會有提示 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <version>2.1.10.RELEASE</version>
</dependency>

配置文件application.properties

#rocketmq
###producer
#該應用是否啓用生產者
rocketmq.producer.isOnOff=on
#發送同一類消息的設置爲同一個group,保證唯一,默認不需要設置,rocketmq會使用ip@pid(pid代表jvm名字)作爲唯一標示
rocketmq.producer.groupName=hmop
#mq的nameserver地址,集羣的時候用分號分隔多個127.0.0.1:9876;127.0.0.1:9877
rocketmq.producer.namesrvAddr=49.235.21.109:9876
#消息最大長度 默認1024*4(4M)
rocketmq.producer.maxMessageSize=4096
#發送消息超時時間,默認3000
rocketmq.producer.sendMsgTimeout=30000
#發送消息失敗重試次數,默認2
rocketmq.producer.retryTimesWhenSendFailed=2
###consumer
##該應用是否啓用消費者
rocketmq.consumer.isOnOff=on
rocketmq.consumer.groupName=hmop
#mq的nameserver地址
rocketmq.consumer.namesrvAddr=49.235.21.109:9876
#該消費者訂閱的主題和tags("*"號表示訂閱該主題下所有的tags),格式:topic~tag1||tag2||tag3;topic2~*;
rocketmq.consumer.topics=test_topic~*;
rocketmq.consumer.consumeThreadMin=20
rocketmq.consumer.consumeThreadMax=64
#設置一次消費消息的條數,默認爲1條
rocketmq.consumer.consumeMessageBatchMaxSize=1

配置屬性類

package com.hmop.tpda.core;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 創建人:sunp
 * 創建時間:2020/4/8 0008
 * 文件名:RocketMqConsumerProperties
 * 版本 修改時間 作者
 * V1.0 2020/4/8 0008 sunp
 */
@Component
@ConfigurationProperties(prefix = "rocketmq.consumer")
@Data
public class RocketMqConsumerProperties {

    private String isOnOff;
    private String groupName;
    private String namesrvAddr;
    private String topics;
    private Integer consumeThreadMin;
    private Integer consumeThreadMax;
    private Integer consumeMessageBatchMaxSize;

}
package com.hmop.tpda.core;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 創建人:sunp
 * 創建時間:2020/4/8 0008
 * 文件名:RocketMqProducerProperties
 * 版本 修改時間 作者
 * V1.0 2020/4/8 0008 sunp
 */
@Component
@ConfigurationProperties(prefix = "rocketmq.producer")
@Data
public class RocketMqProducerProperties {
    private String isOnOff;
    private String groupName;
    private String namesrvAddr;
    private Integer maxMessageSize;
    private Integer sendMsgTimeout;
    private Integer retryTimesWhenSendFailed;
}

配置類

package com.hmop.tpda.configuration;

import com.hmop.tpda.core.RocketMqConsumerProperties;
import com.hmop.tpda.core.RocketMqProducerProperties;
import com.hmop.tpda.listener.RocketMQConsumeMsgListenerProcessor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * 創建人:sunp
 * 創建時間:2020/4/8
 * 文件名:RocketMQConfig
 * 版本 修改時間 作者
 * V1.0 2020/4/8 sunp
 */

@Configuration
@Slf4j
public class RocketMQConfig {

    @Resource
    private RocketMqProducerProperties rocketMqProducerProperties;

    @Resource
    private RocketMqConsumerProperties rocketMqConsumerProperties;

    @Resource
    private RocketMQConsumeMsgListenerProcessor rocketMQConsumeMsgListenerProcessor;

    /***
     * 生產者
     * @return
     */
    @Bean
    public DefaultMQProducer getRocketMQProducer() {
        if (StringUtils.isEmpty(rocketMqProducerProperties.getGroupName())) {
            throw new RuntimeException("rocketMq producer groupName is blank");
        }
        if (StringUtils.isEmpty(rocketMqProducerProperties.getNamesrvAddr())) {
            throw new RuntimeException("rocketMq producer nameServerAddr is blank");
        }
        DefaultMQProducer producer;
        producer = new DefaultMQProducer(rocketMqProducerProperties.getGroupName());
        producer.setNamesrvAddr(rocketMqProducerProperties.getNamesrvAddr());
        //如果需要同一個jvm中不同的producer往不同的mq集羣發送消息,需要設置不同的instanceName
        if (rocketMqProducerProperties.getMaxMessageSize() != null) {
            producer.setMaxMessageSize(rocketMqProducerProperties.getMaxMessageSize());
        }
        if (rocketMqProducerProperties.getSendMsgTimeout() != null) {
            producer.setSendMsgTimeout(rocketMqProducerProperties.getSendMsgTimeout());
        }
        //如果發送消息失敗,設置重試次數,默認爲2次
        if (rocketMqProducerProperties.getRetryTimesWhenSendFailed() != null) {
            producer.setRetryTimesWhenSendFailed(rocketMqProducerProperties.getRetryTimesWhenSendFailed());
        }

        try {
            producer.start();

            log.info(String.format("producer is start ! groupName:[%s],namesrvAddr:[%s]"
                    , rocketMqProducerProperties.getGroupName(), rocketMqProducerProperties.getNamesrvAddr()));
        } catch (MQClientException e) {
            log.error(String.format("producer is error {}"
                    , e.getMessage(), e));
            throw new RuntimeException(e);
        }
        return producer;
    }

    /***
     * 消費者
     * @return
     */
    @Bean
    public DefaultMQPushConsumer getRocketMQConsumer() {
        if (StringUtils.isEmpty(rocketMqConsumerProperties.getGroupName())) {
            throw new RuntimeException("rocketMq consumer groupName is null !");
        }
        if (StringUtils.isEmpty(rocketMqConsumerProperties.getNamesrvAddr())) {
            throw new RuntimeException("rocketMq consumer namesrvAddr is null !");
        }
        if (StringUtils.isEmpty(rocketMqConsumerProperties.getTopics())) {
            throw new RuntimeException("rocketMq consumer topics is null !");
        }
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(rocketMqConsumerProperties.getGroupName());
        consumer.setNamesrvAddr(rocketMqConsumerProperties.getNamesrvAddr());
        consumer.setConsumeThreadMin(rocketMqConsumerProperties.getConsumeThreadMin());
        consumer.setConsumeThreadMax(rocketMqConsumerProperties.getConsumeThreadMax());
        //消息消費處理類
        consumer.registerMessageListener(rocketMQConsumeMsgListenerProcessor);
        /**
         * 設置Consumer第一次啓動是從隊列頭部開始消費還是隊列尾部開始消費
         * 如果非第一次啓動,那麼按照上次消費的位置繼續消費
         */
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
        /**
         * 設置消費模型,集羣還是廣播,默認爲集羣
         */
        //consumer.setMessageModel(MessageModel.CLUSTERING);

        /**
         * 設置一次消費消息的條數,默認爲1條
         */
        consumer.setConsumeMessageBatchMaxSize(rocketMqConsumerProperties.getConsumeMessageBatchMaxSize());
        try {
            /**
             * 設置該消費者訂閱的主題和tag,如果是訂閱該主題下的所有tag,則tag使用*;如果需要指定訂閱該主題下的某些tag,則使用||分割,例如tag1||tag2||tag3
             */
            String[] topicTagsArr = rocketMqConsumerProperties.getTopics().split(";");
            for (String topicTags : topicTagsArr) {
                String[] topicTag = topicTags.split("~");
                consumer.subscribe(topicTag[0], topicTag[1]);
            }
            consumer.start();
            log.info("consumer is start !!! groupName:{},topics:{},namesrvAddr:{}", rocketMqConsumerProperties.getGroupName(),
                    rocketMqConsumerProperties.getTopics(), rocketMqConsumerProperties.getNamesrvAddr());
        } catch (MQClientException e) {
            log.error("consumer is start !!! groupName:{},topics:{},namesrvAddr:{}" , rocketMqConsumerProperties.getGroupName(),
                    rocketMqConsumerProperties.getTopics(), rocketMqConsumerProperties.getNamesrvAddr(), e);
            throw new RuntimeException(e);
        }
        return consumer;
    }
}

消費處理類

package com.hmop.tpda.listener;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * 創建人:sunp
 * 創建時間:2020/4/8 0008
 * 文件名:RocketMQConsumeMsgListenerProcessor
 * 版本 修改時間 作者
 * V1.0 2020/4/8 0008 sunp
 */
@Component
@Slf4j
public class RocketMQConsumeMsgListenerProcessor implements MessageListenerConcurrently {

    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        if(CollectionUtils.isEmpty(msgs)){
            System.out.println("接受到的消息爲空,不處理,直接返回成功");
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        }
        MessageExt messageExt = msgs.get(0);
        System.out.println("接受到的消息爲:"+messageExt.toString());
        if("你的Topic".equals(messageExt.getTopic())){
            if("你的Tag".equals(messageExt.getTags())){
                //TODO 判斷該消息是否重複消費(RocketMQ不保證消息不重複,如果你的業務需要保證嚴格的不重複消息,需要你自己在業務端去重)
                //TODO 獲取該消息重試次數
                int reconsume = messageExt.getReconsumeTimes();
                if(reconsume ==3){//消息已經重試了3次,如果不需要再次消費,則返回成功
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
                //TODO 處理對應的業務邏輯
            }
        }
        // 如果沒有return success ,consumer會重新消費該消息,直到return success
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }

}

測試代碼

package com.hmop.tpda;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * 創建人:sunp
 * 創建時間:2020/4/8 0008
 * 文件名:Test
 * 版本 修改時間 作者
 * V1.0 2020/4/8 0008 sunp
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class DefaultProductTest {

    /**使用RocketMq的生產者*/
    @Autowired
    private DefaultMQProducer defaultMQProducer;

    /**
     * 發送消息
     * @throws InterruptedException
     * @throws MQBrokerException
     * @throws RemotingException
     * @throws MQClientException
     */
    @Test
    public void send() throws MQClientException, RemotingException, MQBrokerException, InterruptedException{
        String msg = "demo msg test";
        System.out.println("開始發送消息:"+msg);
        Message sendMsg = new Message("test_topic","*",msg.getBytes());
        //默認3秒超時
        SendResult sendResult = defaultMQProducer.send(sendMsg);
        System.out.println("消息發送響應信息:"+sendResult.toString());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章