原创

SpringBoot 系列教程(四十一):SpringBoot集成RocketMQ

版权声明: 本文为博主原创文章,转载请注明原文出处!
本文链接:https://thinkingcao.blog.csdn.net/article/details/90933286

 项目结构: SpringBoot的Maven多模块

spring-boot-rocketmq-consumer:消费者

spring-boot-rocketmq-producer:生产者

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

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

 <!--add dependency in pom.xml-->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.3</version>
        </dependency>

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

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

  <parent>
        <groupId>com.thinkingcao.rocketmq</groupId>
        <artifactId>spring-boot-rocketmq</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.thinkingcao.rocketmq</groupId>
    <artifactId>spring-boot-rocketmq</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>spring-boot-rocketmq</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--add dependency in pom.xml-->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.24</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 二、创建生产者

  1、生产者结构图

  

  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;

/**
 * <pre>
 * @desc:
 * @title: RocketMQProducer
 * @author: cao_wencao
 * @date: 2019-06-04 17:52
 * @version: 1.0
 * </pre>
 */
@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;
/**
 * <pre>
 * @desc: 生产者启动类
 * @auth: cao_wencao
 * @date: 2019/6/4 17:40
 * @param null
 * </pre>
 */
@SpringBootApplication
@Slf4j
public class SpringBootRocketmqProducerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootRocketmqProducerApplication.class, args);
    }


}


 

 三、创建消费者

  1.、消费者结构图

  

  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;

/**
 * <pre>
 * @desc:
 * @title: MyConsumer1
 * @author: cao_wencao
 * @date: 2019-06-04 18:02
 * @version: 1.0
 * </pre>
 */

@Slf4j
@Service
@RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1")
public class MyConsumer1 implements RocketMQListener<String> {

    @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;

/**
 * <pre>
 * @desc:
 * @title: MyConsumer2
 * @author: cao_wencao
 * @date: 2019-06-04 18:02
 * @version: 1.0
 * </pre>
 */
@Slf4j
@Service
@RocketMQMessageListener(topic = "test-topic-2", consumerGroup = "my-consumer_test-topic-2")
class MyConsumer2 implements RocketMQListener<OrderPaidEvent> {

    @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;
/**
 * <pre>
 * @desc: 生产者启动类
 * @auth: cao_wencao
 * @date: 2019/6/4 17:40
 * @param null
 * </pre>
 */
@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

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;
}

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

 

 

 

文章最后发布于: 2019-06-05 22:21:17
展开阅读全文
0 个人打赏
私信求帮助

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览