springboot集成rocketmq

  第一步:添加maven依赖

<dependencies>		
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--springboot继承junit的起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope> 
    </dependency>	
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!-- rocketmq所需依赖 -->
    <dependency>
        <groupId>com.alibaba.rocketmq</groupId>
        <artifactId>rocketmq-client</artifactId>
        <version>3.5.8</version>
    </dependency>
</dependencies>

第二步:applicaiton.properties内容如下:

spring.application.name=springboot-rocketmq
server.port=8888

###producer
#该应用是否启用生产者
rocketmq.producer.isOnOff=on
#发送同一类消息的设置为同一个group,保证唯一,默认不需要设置,rocketmq会使用ip@pid(pid代表jvm名字)作为唯一标示
rocketmq.producer.groupName=${spring.application.name}
#mq的nameserver地址
rocketmq.producer.namesrvAddr=192.168.2.203:9876
#消息最大长度 默认1024*4(4M)
rocketmq.producer.maxMessageSize=4096
#发送消息超时时间,默认3000
rocketmq.producer.sendMsgTimeout=3000
#发送消息失败重试次数,默认2
rocketmq.producer.retryTimesWhenSendFailed=2

###consumer
##该应用是否启用消费者
rocketmq.consumer.isOnOff=on
rocketmq.consumer.groupName=${spring.application.name}
#mq的nameserver地址
rocketmq.consumer.namesrvAddr=192.168.2.203:9876
#该消费者订阅的主题和tags("*"号表示订阅该主题下所有的tags),格式:topic~tag1||tag2||tag3;topic2~*;
rocketmq.consumer.topics=DemoTopic~*;
#rocketmq.consumer.topics=DemoTopic;
rocketmq.consumer.consumeThreadMin=20
rocketmq.consumer.consumeThreadMax=64
#设置一次消费消息的条数,默认为1条
rocketmq.consumer.consumeMessageBatchMaxSize=1

 第三步:创建mvaen工程,项目结构图如下:

第四步:编写生产者MQProducerConfiguration 代码:

@SpringBootConfiguration
public class MQProducerConfiguration {
	/**
	 * 发送同一类消息的设置为同一个group,保证唯一,默认不需要设置,rocketmq会使用ip@pid(pid代表jvm名字)作为唯一标示
	 */
	@Value("${rocketmq.producer.groupName}")
	private String groupName;

	@Value("${rocketmq.producer.namesrvAddr}")
	private String namesrvAddr;

	/**
	 * 消息最大大小,默认4M
	 */
	@Value("${rocketmq.producer.maxMessageSize}")
	private Integer maxMessageSize ;
	/**
	 * 消息发送超时时间,默认3秒
	 */
	@Value("${rocketmq.producer.sendMsgTimeout}")
	private Integer sendMsgTimeout;
	/**
	 * 消息发送失败重试次数,默认2次
	 */
	@Value("${rocketmq.producer.retryTimesWhenSendFailed}")
	private Integer retryTimesWhenSendFailed;

	@Bean
	public DefaultMQProducer getRocketMQProducer() throws RocketMQException {

		if(StringUtils.isEmpty(this.groupName)){
			throw new RocketMQException(RocketMQErrorEnum.PARAMM_NULL,"groupName is blank",false);
		}

		if (StringUtils.isEmpty(this.namesrvAddr)) {
			throw new RocketMQException(RocketMQErrorEnum.PARAMM_NULL,"nameServerAddr is blank",false);
		}

		DefaultMQProducer producer;
		producer = new DefaultMQProducer(this.groupName);

		producer.setNamesrvAddr(this.namesrvAddr);
		producer.setCreateTopicKey("AUTO_CREATE_TOPIC_KEY");
		System.out.println(this.groupName+"--"+this.namesrvAddr);
		//如果需要同一个jvm中不同的producer往不同的mq集群发送消息,需要设置不同的instanceName
		//producer.setInstanceName(instanceName);
		if(this.maxMessageSize!=null){
			producer.setMaxMessageSize(this.maxMessageSize);
		}
		if(this.sendMsgTimeout!=null){
			producer.setSendMsgTimeout(this.sendMsgTimeout);
		}
		//如果发送消息失败,设置重试次数,默认为2次
		if(this.retryTimesWhenSendFailed!=null){
			producer.setRetryTimesWhenSendFailed(this.retryTimesWhenSendFailed);
		}
		try {
			producer.start();
			System.out.println(String.format("producer is start ! groupName:[%s],namesrvAddr:[%s]"
					, this.groupName, this.namesrvAddr));
		} catch (MQClientException e) {
			System.out.println(String.format("producer is error {}"
					, e.getMessage(),e));
			throw new RocketMQException(e);
		}
		return producer;

	}
}

 第五步:编写消费者代码,分为两部分,一部分是监听,另一部分是消费者

@Component
public class MQConsumeMsgListenerProcessor implements MessageListenerConcurrently{
	
	public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
		
		if(CollectionUtils.isEmpty(msgs)){
			System.out.println("接收到的消息为空,不做任何处理");
			return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
		}
		MessageExt messageExt = msgs.get(0);
		String msg = new String(messageExt.getBody());
		System.out.println("接收到的消息是:"+msg);
		if(messageExt.getTopic().equals("你的topic")){
			if(messageExt.getTags().equals("你的tag")){
				int reconsumeTimes = messageExt.getReconsumeTimes();
				if(reconsumeTimes == 3){
					return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
				}
				//TODO 处理对应的业务逻辑
			}
		}
		
		return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
	}
}
@SpringBootConfiguration
public class MQConsumerConfiguration {
	public static final Logger logger = LoggerFactory.getLogger(MQConsumerConfiguration.class);

	@Value("${rocketmq.consumer.namesrvAddr}")
	private String namesrvAddr;
	@Value("${rocketmq.consumer.groupName}")
	private String groupName;
	@Value("${rocketmq.consumer.consumeThreadMin}")
	private int consumeThreadMin;
	@Value("${rocketmq.consumer.consumeThreadMax}")
	private int consumeThreadMax;
	@Value("${rocketmq.consumer.topics}")
	private String topics;
	@Value("${rocketmq.consumer.consumeMessageBatchMaxSize}")
	private int consumeMessageBatchMaxSize;

	@Autowired
	private MQConsumeMsgListenerProcessor mqMessageListenerProcessor;
	
	@Bean
	public DefaultMQPushConsumer getRocketMQConsumer() throws RocketMQException{
		if (StringUtils.isEmpty(groupName)){
			throw new RocketMQException(RocketMQErrorEnum.PARAMM_NULL,"groupName is null !!!",false);
		}
		if (StringUtils.isEmpty(namesrvAddr)){
			throw new RocketMQException(RocketMQErrorEnum.PARAMM_NULL,"namesrvAddr is null !!!",false);
		}
		if(StringUtils.isEmpty(topics)){
			throw new RocketMQException(RocketMQErrorEnum.PARAMM_NULL,"topics is null !!!",false);
		}

		DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(groupName);
		consumer.setNamesrvAddr(namesrvAddr);
		consumer.setConsumeThreadMin(consumeThreadMin);
		consumer.setConsumeThreadMax(consumeThreadMax);
		consumer.registerMessageListener(mqMessageListenerProcessor);

		/**
		 * 设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费
		 * 如果非第一次启动,那么按照上次消费的位置继续消费
		 */
		consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
		/**
		 * 设置消费模型,集群还是广播,默认为集群
		 */
		//consumer.setMessageModel(MessageModel.CLUSTERING);

		/**
		 * 设置一次消费消息的条数,默认为1条
		 */
		consumer.setConsumeMessageBatchMaxSize(consumeMessageBatchMaxSize);

		try {
			/**
			 * 设置该消费者订阅的主题和tag,如果是订阅该主题下的所有tag,
			 * 则tag使用*;如果需要指定订阅该主题下的某些tag,则使用||分割,例如tag1||tag2||tag3
			 */
			String[] topicTagsArr = topics.split(";");
        	for (String topicTags : topicTagsArr) {
        		String[] topicTag = topicTags.split("~");
        		consumer.subscribe(topicTag[0],topicTag[1]);
			}
			consumer.start();
			System.out.println("consumer is start !!! groupName:{},topics:{},namesrvAddr:{},"+groupName+","+topics+","+namesrvAddr+"");
		} catch (Exception e) {
			System.out.println("consumer is start error !!! groupName:{},topics:{},namesrvAddr:{},"+groupName+","+topics+","+namesrvAddr+"");
			throw new RocketMQException(e);
		}

		return consumer;
	}

}

第六步:一些异常类和常量的封装

public interface ErrorCode extends Serializable {
	
	/**
	 * 错误码
	 * 
	 * @return
	 */
	String getCode();

	/**
	 * 错误信息
	 * 
	 * @return
	 */
	String getMsg();
}
public class AppException extends RuntimeException {

	private static final long serialVersionUID = 1L;
	
	/**
     * 错误编码
     */
    protected ErrorCode errCode;

    /**
     * 错误信息
     */
    protected String errMsg;

    /**
     * 无参构造函数
     */
    public AppException() {
        super();
    }
    public AppException(Throwable e) {
        super(e);
    }
    
    public AppException(ErrorCode errCode, String... errMsg) {
        super(errCode.getMsg());
        this.errCode = errCode;
        setErrMsg(errMsg,true);
    }
    
    public AppException(ErrorCode errCode, String errMsg,Boolean isTransfer) {
        super(errMsg);
        this.errCode = errCode;
        setErrMsg(new String[]{errMsg},isTransfer);
    }
    
    /**
     * 构造函数
     *
     * @param cause 异常
     */
    public AppException(ErrorCode errCode, Throwable cause, String... errMsg) {
        super(errCode.getCode() + errCode.getMsg(), cause);
        this.errCode = errCode;
        setErrMsg(errMsg,true);
    }

    public ErrorCode getErrCode() {
        return errCode;
    }

    public void setErrCode(ErrorCode errCode) {
        this.errCode = errCode;
    }

    public String getErrMsg() {
        return this.errMsg;
    }

    public void setErrMsg(String[] errMsg,Boolean isTransfer) {

        if (null != errMsg &&errMsg.length>0) {
        	if(errCode.getMsg().contains("%s") && isTransfer){
        		this.errMsg = String.format(errCode.getMsg(), errMsg);
        	}else{
        		StringBuffer sf = new StringBuffer();
        		for (String msg : errMsg) {
					sf.append(msg+";");
				}
        		this.errMsg = sf.toString();
        	}
        }else{
        	this.errMsg = errCode.getMsg();
        }

    }

    public static void main(String[] args) {
        String str = "ERRCode:1004--对象不存在:[%s]";
        if (str.contains("%s")){
         System.out.println("包含");
        }
    }
}
public enum RocketMQErrorEnum implements ErrorCode {

	/******** 公共 ********/
	PARAMM_NULL("MQ_001", "参数为空"),

	/******** 生产者 *******/

	/******** 消费者 *******/
	NOT_FOUND_CONSUMESERVICE("MQ_100", "根据topic和tag没有找到对应的消费服务"), 
	
	HANDLE_RESULT_NULL("MQ_101", "消费方法返回值为空"),
	
	CONSUME_FAIL("MQ_102", "消费失败");

	private String code;
	private String msg;

	private RocketMQErrorEnum(String code, String msg) {
		this.code = code;
		this.msg = msg;
	}

	@Override
	public String getCode() {
		return this.code;
	}

	@Override
	public String getMsg() {
		return this.msg;
	}
}
public class RocketMQException extends AppException {
	private static final long serialVersionUID = 1L;

	/**
	 * 无参构造函数
	 */
	public RocketMQException() {
		super();
	}

	public RocketMQException(Throwable e) {
		super(e);
	}

	public RocketMQException(ErrorCode errorType) {
		super(errorType);
	}

	public RocketMQException(ErrorCode errorCode, String... errMsg) {
		super(errorCode, errMsg);
	}

	/**
	 * 封装异常
	 * 
	 * @param errorCode
	 * @param errMsg
	 * @param isTransfer
	 *            是否转换异常信息,如果为false,则直接使用errMsg信息
	 */
	public RocketMQException(ErrorCode errorCode, String errMsg, Boolean isTransfer) {
		super(errorCode, errMsg, isTransfer);
	}

	public RocketMQException(ErrorCode errCode, Throwable cause, String... errMsg) {
		super(errCode, cause, errMsg);
	}
}

第七步:创建测试类DefaultProductTest

@SpringBootTest
@RunWith(SpringRunner.class)
public class DefaultProductTest {
	
	/**使用RocketMq的生产者*/
    @Autowired
    private DefaultMQProducer defaultMQProducer;
	
    @Test
    public void send() throws MQClientException, RemotingException, MQBrokerException, InterruptedException{
        String msg = "demo msg test";
        System.out.println("开始发送消息:"+msg);
        Message sendMsg = new Message("DemoTopic","DemoTag",msg.getBytes());
        
        //默认3秒超时
        SendResult sendResult = defaultMQProducer.send(sendMsg);
        System.out.println("消息发送响应信息:"+sendResult.toString());
    }
}

第八步:执行测试

       依次启动rocketmqnameserverbroker,然后执行DefaultProductTest这个类,输出结果如下所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐的小三菊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值