SpringBoot | 第四十一章:SpringBoot集成RocketMQ

 项目结构: SpringBoot的Maven多模块

spring-boot-rocketmq-consumer:消费者

spring-boot-rocketmq-producer:生产者

SpringBoot | 第四十一章:SpringBoot集成RocketMQ_第1张图片

一、搭建SpringBoot基础框架项目环境

  1.RocketMQ的SpringBoot版本官方starter:https://github.com/apache/rocketmq-spring,当前最新版本为2.0.3

 
        
            org.apache.rocketmq
            rocketmq-spring-boot-starter
            2.0.3
        

  2.新建上述Maven多模块项目,在Maven父模块spring-boot-rocketmq中引入Maven依赖,完整pom.xml如下:

 子模块spring-boot-rocketmq-producer生产者和spring-boot-rocketmq-consumer消费者中引入下面就可以继承父模块中的Maven依赖

  
        com.thinkingcao.rocketmq
        spring-boot-rocketmq
        0.0.1-SNAPSHOT
         
    


    4.0.0
    com.thinkingcao.rocketmq
    spring-boot-rocketmq
    0.0.1-SNAPSHOT
    pom

    spring-boot-rocketmq
    Demo project for Spring Boot

    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.5.RELEASE
         
    
    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
            org.apache.rocketmq
            rocketmq-spring-boot-starter
            2.0.3
        
        
            com.alibaba
            fastjson
            1.2.24
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


 二、创建生产者

  1、生产者结构图

  SpringBoot | 第四十一章:SpringBoot集成RocketMQ_第2张图片

  2、新建实体类OrderPaidEvent.java 

package com.thinkingcao.rocketmq.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

@Data
@AllArgsConstructor

public class OrderPaidEvent implements Serializable {

    private String orderId;

    private Integer paidMoney;
}

 3、新建生产者RocketMQProducer.java

package com.thinkingcao.rocketmq.producer;

import com.thinkingcao.rocketmq.entity.OrderPaidEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 
 * @desc:
 * @title: RocketMQProducer
 * @author: cao_wencao
 * @date: 2019-06-04 17:52
 * @version: 1.0
 * 
*/ @Slf4j @Component public class RocketMQProducer implements CommandLineRunner { @Resource private RocketMQTemplate rocketMQTemplate; @Override public void run(String... args) throws Exception { log.info("-----------生产者开始生产消息-----------"); rocketMQTemplate.convertAndSend("test-topic-1", "Hello, World!"); log.info("生产者生产第一个消息完成: 主题:{}, 内容:{}","test-topic-1","Hello, World!"); rocketMQTemplate.convertAndSend("test-topic-2", new OrderPaidEvent("orderId-0001", 88)); log.info("生产者生产第二个消息完成: 主题:{}, 内容:{}","test-topic-2",new OrderPaidEvent("orderId-0001", 88)); log.info("-----------生产者生产消息结束-----------"); } }

 4、新建application.properties配置文件

##生产者配置

# 端口
server.port=7777

# NameServer地址
rocketmq.name-server=127.0.0.1:9876
# 生产者的组名
rocketmq.producer.group=ProducerGroup
# 发送消息超时时间
rocketmq.producer.send-message-timeout=3000
# 消息最大长度
rocketmq.producer.max-message-size=4194304
rocketmq.producer.compress-message-body-threshold=4096
rocketmq.producer.retry-times-when-send-async-failed=0
rocketmq.producer.retry-next-server=true
rocketmq.producer.retry-times-when-send-failed=2

5、新建生产者启动类SpringBootRocketmqProducerApplication.java

package com.thinkingcao.rocketmq;

import com.thinkingcao.rocketmq.entity.OrderPaidEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.Resource;
/**
 * 
 * @desc: 生产者启动类
 * @auth: cao_wencao
 * @date: 2019/6/4 17:40
 * @param null
 * 
*/ @SpringBootApplication @Slf4j public class SpringBootRocketmqProducerApplication { public static void main(String[] args) { SpringApplication.run(SpringBootRocketmqProducerApplication.class, args); } }

 

 三、创建消费者

  1.、消费者结构图

  SpringBoot | 第四十一章:SpringBoot集成RocketMQ_第3张图片

  2、新建实体类OrderPaidEvent.java   同生产者一样

  3、新建两个消费者MyConsumer1.java和MyConsumer2.java

  MyConsumer1

package com.thinkingcao.rocketmq.consumer;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;

/**
 * 
 * @desc:
 * @title: MyConsumer1
 * @author: cao_wencao
 * @date: 2019-06-04 18:02
 * @version: 1.0
 * 
*/ @Slf4j @Service @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1") public class MyConsumer1 implements RocketMQListener { @Override public void onMessage(String message) { log.info("消费者消费消息开始-----------"); //JSONObject jsonObject = JSON.parseObject(message); //OrderPaidEvent orderPaidEvent = JSONObject.parseObject(message, OrderPaidEvent.class); log.info("消费者开始接收第一个消息received message: {}", message); } }

  MyConsumer2

package com.thinkingcao.rocketmq.consumer;

import com.thinkingcao.rocketmq.entity.OrderPaidEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;

/**
 * 
 * @desc:
 * @title: MyConsumer2
 * @author: cao_wencao
 * @date: 2019-06-04 18:02
 * @version: 1.0
 * 
*/ @Slf4j @Service @RocketMQMessageListener(topic = "test-topic-2", consumerGroup = "my-consumer_test-topic-2") class MyConsumer2 implements RocketMQListener { @Override public void onMessage(OrderPaidEvent orderPaidEvent) { log.info("消费者开始接收第二个消息received orderPaidEvent: {}", orderPaidEvent); log.info("消费者消费消息结束-----------"); } }

  4、新建application.properties配置文件

##消费者配置

# 端口
server.port=8888

# NameServer地址
rocketmq.name-server=127.0.0.1:9876
# 生产者组名
rocketmq.producer.group=ProducerGroup

rocketmq.producer.enable-msg-trace=true
rocketmq.producer.customized-trace-topic=my-trace-topic

5、新建消费者启动类SpringBootRocketmqConsumerApplication.java

package com.thinkingcao.rocketmq;

import com.thinkingcao.rocketmq.entity.OrderPaidEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.Resource;
/**
 * 
 * @desc: 生产者启动类
 * @auth: cao_wencao
 * @date: 2019/6/4 17:40
 * @param null
 * 
*/ @SpringBootApplication @Slf4j public class SpringBootRocketmqProducerApplication { public static void main(String[] args) { SpringApplication.run(SpringBootRocketmqProducerApplication.class, args); } }

四、测试生产者生产消息和消费者消费消息

 1、生产者这时候正常生产消息

 2019-06-05 20:37:13.429  INFO 24436 --- [           main] c.t.rocketmq.producer.RocketMQProducer   : -----------生产者开始生产消息-----------
2019-06-05 20:37:13.983  INFO 24436 --- [           main] c.t.rocketmq.producer.RocketMQProducer   : 生产者生产第一个消息完成: 主题:test-topic-1, 内容:Hello, World!
2019-06-05 20:37:14.042  INFO 24436 --- [           main] c.t.rocketmq.producer.RocketMQProducer   : 生产者生产第二个消息完成: 主题:test-topic-2, 内容:OrderPaidEvent(orderId=orderId-0001, paidMoney=88)
2019-06-05 20:37:14.043  INFO 24436 --- [           main] c.t.rocketmq.producer.RocketMQProducer   : -----------生产者生产消息结束-----------

2、但是有个问题出现了,消费者在消费消息的时候报了一个异常,异常如下:

 

2019-06-05 20:37:14.552  INFO 24024 --- [MessageThread_1] c.t.rocketmq.consumer.MyConsumer1        : 消费者消费消息开始-----------
2019-06-05 20:37:14.552  INFO 24024 --- [MessageThread_1] c.t.rocketmq.consumer.MyConsumer1        : 消费者开始接收第一个消息received message: Hello, World!
2019-06-05 20:37:14.661  INFO 24024 --- [MessageThread_1] a.r.s.s.DefaultRocketMQListenerContainer : convert failed. str:{"orderId":"orderId-0001","paidMoney":88}, msgType:class com.thinkingcao.rocketmq.entity.OrderPaidEvent
2019-06-05 20:37:14.665  WARN 24024 --- [MessageThread_1] a.r.s.s.DefaultRocketMQListenerContainer : consume message failed. messageExt:MessageExt [queueId=0, storeSize=284, queueOffset=4, sysFlag=0, bornTimestamp=1559738234040, bornHost=/192.168.86.1:61749, storeTimestamp=1559738234041, storeHost=/192.168.86.1:10911, msgId=C0A8560100002A9F00000000001E5BF0, commitLogOffset=1989616, bodyCRC=1717770219, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='test-topic-2', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=5, CONSUME_START_TIME=1559738234552, id=80b13c45-8db1-6671-8538-c4f61b48a269, UNIQ_KEY=C0A801035F7458644D46190628B80003, WAIT=false, contentType=text/plain, timestamp=1559738234038}, body=[123, 34, 111, 114, 100, 101, 114, 73, 100, 34, 58, 34, 111, 114, 100, 101, 114, 73, 100, 45, 48, 48, 48, 49, 34, 44, 34, 112, 97, 105, 100, 77, 111, 110, 101, 121, 34, 58, 56, 56, 125], transactionId='null'}]

java.lang.RuntimeException: cannot convert message to class com.thinkingcao.rocketmq.entity.OrderPaidEvent
    at org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.doConvertMessage(DefaultRocketMQListenerContainer.java:382) ~[rocketmq-spring-boot-2.0.3.jar:2.0.3]
    at org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.access$100(DefaultRocketMQListenerContainer.java:57) ~[rocketmq-spring-boot-2.0.3.jar:2.0.3]
    at org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer$DefaultMessageListenerConcurrently.consumeMessage(DefaultRocketMQListenerContainer.java:330) ~[rocketmq-spring-boot-2.0.3.jar:2.0.3]
    at org.apache.rocketmq.client.impl.consumer.ConsumeMessageConcurrentlyService$ConsumeRequest.run(ConsumeMessageConcurrentlyService.java:411) [rocketmq-client-4.5.1.jar:4.5.1]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_25]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_25]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.thinkingcao.rocketmq.entity.OrderPaidEvent` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"orderId":"orderId-0001","paidMoney":88}"; line: 1, column: 2]
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004) ~[jackson-databind-2.9.8.jar:2.9.8]
    at org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.doConvertMessage(DefaultRocketMQListenerContainer.java:379) ~[rocketmq-spring-boot-2.0.3.jar:2.0.3]
    ... 8 common frames omitted
 

异常代码:

 cannot convert message to class com.thinkingcao.rocketmq.entity.OrderPaidEvent

SpringBoot | 第四十一章:SpringBoot集成RocketMQ_第4张图片3、解决:经过很长时间的查询发现是我的实体类OrderPaidEvent没有无参的构造函数,因为序列化和反序列化需要构造函数

这时候实体OrderPaidEvent应该如下:加上一个无参的构造方法 @NoArgsConstructor,所以以后得注意了,在序列化和反序列化时,Java实体类是需要一个无参的构造方法的


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderPaidEvent implements Serializable {

    private String orderId;

    private Integer paidMoney;
}

再次测试时就好了,消息正常消费

SpringBoot | 第四十一章:SpringBoot集成RocketMQ_第5张图片

 

 

 

你可能感兴趣的:(#,【4】RocketMQ,SpringBoot2.x)