1、快速实战
这部分我们看下SpringBoot如何快速集成RocketMQ。
在使用SpringBoot的starter集成包时,要特别注意版本。因为SpringBoot集成RocketMQ的starter依赖是由Spring社区提供的,目前正在快速迭代的过程当中,不同版本之间的差距非常大,甚至基础的底层对象都会经常有改动。例如如果使用rocketmq-spring-boot-starter:2.0.4版本开发的代码,升级到目前最新的rocketmq-spring-boot-starter:2.1.1后,基本就用不了了。
我们创建一个maven工程,引入关键依赖:
<dependencies><dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.1.1</version><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></exclusion><exclusion><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></exclusion><exclusion><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.1.6.RELEASE</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency></dependencies>
rocketmq-spring-boot-starter:2.1.1引入的SpringBoot包版本是2.0.5.RELEASE,这里把SpringBoot的依赖包升级了一下。
然后我们以SpringBoot的方式,快速创建一个简单的Demo
启动类:
@SpringBootApplicationpublic class RocketMQScApplication {public static void main(String[] args) {SpringApplication.run(RocketMQScApplication.class,args);}}
配置文件 application.properties
#NameServer地址rocketmq.name-server=192.168.232.128:9876#默认的消息生产者组rocketmq.producer.group=springBootGroup
消息生产者
package com.roy.rocket.basic;import org.apache.rocketmq.client.exception.MQClientException;import org.apache.rocketmq.client.producer.SendResult;import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;import org.apache.rocketmq.spring.core.RocketMQTemplate;import org.springframework.messaging.Message;import org.springframework.messaging.support.MessageBuilder;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.io.UnsupportedEncodingException;/*** @author :dlz* @date :Created in 2020/10/22* @description:**/@Componentpublic class SpringProducer {@Resourceprivate RocketMQTemplate rocketMQTemplate;//发送普通消息的示例public void sendMessage(String topic,String msg){this.rocketMQTemplate.convertAndSend(topic,msg);}//发送事务消息的示例public void sendMessageInTransaction(String topic,String msg) throws InterruptedException {String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"};for (int i = 0; i < 10; i++) {Message<String> message = MessageBuilder.withPayload(msg).build();String destination =topic+":"+tags[i % tags.length];SendResult sendResult = rocketMQTemplate.sendMessageInTransaction(destination, message,destination);System.out.printf("%s%n", sendResult);Thread.sleep(10);}}}
消息消费者
package com.roy.rocket.basic;import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;import org.apache.rocketmq.spring.core.RocketMQListener;import org.springframework.stereotype.Component;/*** @author :dlz* @date :Created in 2020/10/22* @description:**/@Component@RocketMQMessageListener(consumerGroup = "MyConsumerGroup", topic = "TestTopic")public class SpringConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received message : "+ message);}}
SpringBoot集成RocketMQ,消费者部分的核心就在这个@RocketMQMessageListener注解上。所有消费者的核心功能也都会集成到这个注解中。所以我们还要注意下这个注解里面的属性:
例如:消息过滤可以由里面的selectorType属性和selectorExpression来定制
消息有序消费还是并发消费则由consumeMode属性定制。
消费者是集群部署还是广播部署由messageModel属性定制。
然后关于事务消息,还需要配置一个事务消息监听器:
package com.roy.rocket.config;import org.apache.commons.lang3.StringUtils;import org.apache.rocketmq.client.producer.LocalTransactionState;import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;import org.apache.rocketmq.spring.support.RocketMQUtil;import org.springframework.messaging.Message;import org.springframework.messaging.converter.StringMessageConverter;import java.util.concurrent.ConcurrentHashMap;/*** @author :楼兰* @date :Created in 2020/11/5* @description:**/@RocketMQTransactionListener(rocketMQTemplateBeanName = "rocketMQTemplate")public class MyTransactionImpl implements RocketMQLocalTransactionListener {private ConcurrentHashMap<Object, String> localTrans = new ConcurrentHashMap<>();@Overridepublic RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {Object id = msg.getHeaders().get("id");String destination = arg.toString();localTrans.put(id,destination);org.apache.rocketmq.common.message.Message message = RocketMQUtil.convertToRocketMessage(new StringMessageConverter(),"UTF-8",destination, msg);String tags = message.getTags();if(StringUtils.contains(tags,"TagA")){return RocketMQLocalTransactionState.COMMIT;}else if(StringUtils.contains(tags,"TagB")){return RocketMQLocalTransactionState.ROLLBACK;}else{return RocketMQLocalTransactionState.UNKNOWN;}}@Overridepublic RocketMQLocalTransactionState checkLocalTransaction(Message msg) {//SpringBoot的消息对象中,并没有transactionId这个属性。跟原生API不一样。// String destination = localTrans.get(msg.getTransactionId());return RocketMQLocalTransactionState.COMMIT;}}
这样我们启动应用后,就能够通过访问 http://localhost:8080/MQTest/sendMessage?message=123 接口来发送一条简单消息。并在SpringConsumer中消费到。
也可以通过访问http://localhost:8080/MQTest/sendTransactionMessage?message=123 ,来发送一条事务消息。
这里可以看到,对事务消息,SpringBoot进行封装时,就缺少了transactionId,这在事务控制中是非常关键的。
如果提示没有主题,那可以先创建一个主题。
2、其他更多消息类型:
对于其他的消息类型,文档中就不一一记录了。具体可以参见源码中的junit测试案例。
3、总结:
- SpringBoot 引入org.apache.rocketmq:rocketmq-spring-boot-starter依赖后,就可以通过内置的RocketMQTemplate来与RocketMQ交互。相关属性都以rockemq.开头。具体所有的配置信息可以参见org.apache.rocketmq.spring.autoconfigure.RocketMQProperties这个类。
- SpringBoot依赖中的Message对象和RocketMQ-client中的Message对象是两个不同的对象,这在使用的时候要非常容易弄错。例如RocketMQ-client中的Message里的TAG属性,在SpringBoot依赖中的Message中就没有。Tag属性被移到了发送目标中,与Topic一起,以Topic:Tag的方式指定。
- 最后强调一次,一定要注意版本。rocketmq-spring-boot-starter的更新进度一般都会略慢于RocketMQ的版本更新,并且版本不同会引发很多奇怪的问题。apache有一个官方的rocketmq-spring示例,地址:https://github.com/apache/rocketmq-spring.git 以后如果版本更新了,可以参考下这个示例代码。
