java 如何在 Spring Boot 和 RabbitMQ 中配置和接收并将 jSON 负载转换为域对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29592543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to configure and receiveAndConvert jSON payload into domain Object in Spring Boot and RabbitMQ
提问by OchiengOlanga
Recently I have been having a keen interest on Microservice Architecture using Spring Boot. My implementation has two Spring boot applications;
最近对使用 Spring Boot 的微服务架构产生了浓厚的兴趣。我的实现有两个 Spring 启动应用程序;
Application Onereceives requests from a RESTful API, converts and sends jSON payload to a RabbitMQ queueA.
应用程序一接收来自 RESTful API 的请求,转换并发送 JSON 负载到RabbitMQ queueA。
Application Two, has subscribed to queueA, receives the jSON payload(Domain Object User) and is supposed to activate a service within Application Two eg. send email to a user.
应用程序二已订阅queueA,接收 jSON 有效负载(域对象用户)并应该激活应用程序二中的服务,例如。向用户发送电子邮件。
Using no XML in my Application Twoconfiguration, how do I configure a converter that will convert the jSON payload received from RabbitMQ into a Domain Object User.
在我的应用程序二配置中不使用 XML ,如何配置一个转换器,将从 RabbitMQ 接收到的 JSON 有效负载转换为域对象用户。
Below are snippets from Spring Boot configurations on Application Two
以下是应用程序二上 Spring Boot 配置的片段
Application.class
应用程序类
@SpringBootApplication
@EnableRabbit
public class ApplicationInitializer implements CommandLineRunner {
final static String queueName = "user-registration";
@Autowired
RabbitTemplate rabbitTemplate;
@Autowired
AnnotationConfigApplicationContext context;
@Bean
Queue queue() {
return new Queue(queueName, false);
}
@Bean
TopicExchange topicExchange() {
return new TopicExchange("user-registrations");
}
@Bean
Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(queueName);
}
@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(queueName);
container.setMessageListener(listenerAdapter);
return container;
}
public static void main(String[] args) {
SpringApplication.run(ApplicationInitializer.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("Waiting for messages...");
}
}
TestService.java
测试服务.java
@Component
public class TestService {
/**
* This test verifies whether this consumer receives message off the user-registration queue
*/
@RabbitListener(queues = "user-registration")
public void testReceiveNewUserNotificationMessage(User user) {
// do something like, convert payload to domain object user and send email to this user
}
}
回答by jonashackt
I had the same problem and after some research and testing I learned, that there is more than one way to configure your RabbitMQ-Receiver in SpringBoot, but it is important to choose one and stick with that.
我遇到了同样的问题,经过一些研究和测试,我了解到在 SpringBoot 中配置 RabbitMQ-Receiver 的方法不止一种,但重要的是选择一种方法并坚持下去。
If you decide to go with the Annotation Driven Listener Endpoint, what I derive from your usage of @EnableRabbit and @RabbitListener, than the configuration you posted didn′t work for me. What worked is the following:
如果您决定使用Annotation Driven Listener Endpoint,我从您对 @EnableRabbit 和 @RabbitListener 的使用中得出的结论,那么您发布的配置对我不起作用。有效的是以下内容:
Derive your Configuration Class from org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer and override the Method configureRabbitListeners as follows:
从 org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer 派生您的配置类并覆盖方法 configureRabbitListeners 如下:
@Override
public void configureRabbitListeners(
RabbitListenerEndpointRegistrar registrar) {
registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
}
and add a MessageHandlerFactory:
并添加一个 MessageHandlerFactory:
@Bean
public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
factory.setMessageConverter(new MappingHymanson2MessageConverter());
return factory;
}
Additionally you need to define SimpleRabbitListenerContainerFactory (as you already did) and Autowire the corresponding ConnectionFactory:
此外,您需要定义 SimpleRabbitListenerContainerFactory (正如您已经做过的那样)并自动装配相应的 ConnectionFactory:
@Autowired
public ConnectionFactory connectionFactory;
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setConcurrentConsumers(3);
factory.setMaxConcurrentConsumers(10);
return factory;
}
Finishing your Configuration, you need to define the Bean, which handles your Messages and inherits the @RabbitListerner-Annotations. For me I named that EventResultHandler (you named it TestService):
完成配置后,您需要定义 Bean,它处理您的消息并继承 @RabbitListerner-Annotations。对我来说,我将该 EventResultHandler 命名为(您将其命名为 TestService):
@Bean
public EventResultHandler eventResultHandler() {
return new EventResultHandler();
}
Then in your EventResultHandler (or TestService) you define the @RabbitListener-Methods with their corresponding Queues and the Payload (= the POJO, where your JSON-Message is serialized to):
然后在您的 EventResultHandler(或 TestService)中,您定义 @RabbitListener-Methods 及其相应的队列和有效负载(= POJO,您的 JSON-Message 序列化到其中):
@Component
public class EventResultHandler {
@RabbitListener(queues=Queues.QUEUE_NAME_PRESENTATION_SERVICE)
public void handleMessage(@Payload Event event) {
System.out.println("Event received");
System.out.println("EventType: " + event.getType().getText());
}
}
I ommited the needed definition and binding of Queues and Exchanges - you can do that either in one or in another Microservice - or in RabbitMQ-Server manually... But you for sure have to do that.
我省略了队列和交换所需的定义和绑定——你可以在一个或另一个微服务中做到这一点——或者在 RabbitMQ-Server 中手动完成......但你肯定必须这样做。
回答by Nicolas Labrot
Create a Hymanson message converter and set it with MessageListenerAdapter#setMessageConverter
创建一个Hyman逊消息转换器并将其设置为 MessageListenerAdapter#setMessageConverter
@Bean
public MessageConverter jsonMessageConverter() {
return new Hymanson2JsonMessageConverter();
}
Where do come from MessageListenerAdapter
?
从哪里来MessageListenerAdapter
?
回答by mr.M
As per Spring Boot version 2.1.4.RELEASE, you could do the following:
根据 Spring Boot 2.1.4.RELEASE 版本,您可以执行以下操作:
- Declare "decorated" RabbitMq template with Hymanson message converter:
- 使用 Hymanson 消息转换器声明“装饰”的 RabbitMq 模板:
@Bean
RabbitTemplate rabbitTemplate(RabbitTemplate rabbitTemplate) {
rabbitTemplate.setMessageConverter(new Hymanson2JsonMessageConverter());
return rabbitTemplate
}
- Read message from the queue:
- 从队列中读取消息:
var receievedValie = rabbitTemplate.receiveAndConvert("TestQueue", new ParameterizedTypeReference<Integer>() {
@Override
public Type getType() {
return super.getType();
}
})