在 RabbitListener 中处理通用类型
Handle Generic Type in RabbitListener
在我的 springboot 应用程序中,我正在创建一条包含通用类型的消息,如下所示:
public List<QMessage<T>> composeMessage(String entityName, List<T> input) {
if (CollectionUtils.isEmpty(input)) {
return null;
}
log.debug("Composing message to send");
List<QMessage<T>> result = new ArrayList<>();
input.forEach(el -> {
QMessage<T> tmp = new QMessage<>();
tmp.setSourceId(getSourceId(el));
tmp.setEntityName(entityName);
tmp.setData(el);
result.add(tmp);
});
return result;
}
public void convertAndPublishList(List<QMessage<T>> items) {
try {
log.debug("Converting message to JSON and publishing to RabbitMQ");
rabbitTemplate.convertAndSend(MQConfig.WD_COMMONS_QUEUE_EXCHANGE, MQConfig.WD_COMMONS_QUEUE_ROUTING_KEY, items);
} catch (AmqpException e) {
log.error("Error during message publishing to RabbitMQ. Exception: {}", e.getMessage());
throw new BlenderProducerException(e.getMessage(), e);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class QMessage<T> implements Serializable {
private static final long serialVersionUID = 9095736695643670685L;
private Long sourceId;
private String entityName;
private T data;
}
在听众方面,我想以某种方式处理泛型,这就是我尝试过的:
@Slf4j
@Component
@RequiredArgsConstructor
@RabbitListener(queues = MQConfig.WD_COMMONS_QUEUE)
public class WDCommonsListeners {
@RabbitHandler
public void handleA(List<QMessage<Dog>> message) {
System.out.println("handle 1");
}
@RabbitHandler
public void handleB(List<QMessage<Cat>> message) {
System.out.println("handle 2");
}
}
但我收到此异常消息:
org.springframework.amqp.AmqpException:负载类型的方法不明确:class java.util.ArrayList:handleA 和 handleB
考虑 Cat 和 Dog class 都在扩展 Animal class
我也尝试过使用未知类型的消息,但我收到了一个对象的 LinkedList:
@RabbitListener(queues = MQConfig.WD_COMMONS_QUEUE)
public void listener(List<QMessage<?>> message) throws IOException {
if (!CollectionUtils.isEmpty(message)) {
for (QMessage<?> msg : message) {
System.out.println("msg");
}
}
也许我必须从消息中获取 JSON 并使用 ObjectMapper 将其转换为对象?
它只是不检查方法参数的通用类型:methodParameter.getParameterType().isAssignableFrom(payloadClass)
。所以,这就是你产生歧义的原因。
由于您的逻辑很难处理集合及其深层嵌套的泛型类型,我真的建议使用单个 @RabbitListener
并手动执行相应的路由。
必须为 TypePrecedence.TYPE_ID
配置 DefaultJackson2JavaTypeMapper
以使其在调用侦听器方法之前将传入数据转换为 List<QMessage<?>>
:https://docs.spring.io/spring-amqp/docs/current/reference/html/#Jackson2JsonMessageConverter-from-message
在我的 springboot 应用程序中,我正在创建一条包含通用类型的消息,如下所示:
public List<QMessage<T>> composeMessage(String entityName, List<T> input) {
if (CollectionUtils.isEmpty(input)) {
return null;
}
log.debug("Composing message to send");
List<QMessage<T>> result = new ArrayList<>();
input.forEach(el -> {
QMessage<T> tmp = new QMessage<>();
tmp.setSourceId(getSourceId(el));
tmp.setEntityName(entityName);
tmp.setData(el);
result.add(tmp);
});
return result;
}
public void convertAndPublishList(List<QMessage<T>> items) {
try {
log.debug("Converting message to JSON and publishing to RabbitMQ");
rabbitTemplate.convertAndSend(MQConfig.WD_COMMONS_QUEUE_EXCHANGE, MQConfig.WD_COMMONS_QUEUE_ROUTING_KEY, items);
} catch (AmqpException e) {
log.error("Error during message publishing to RabbitMQ. Exception: {}", e.getMessage());
throw new BlenderProducerException(e.getMessage(), e);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class QMessage<T> implements Serializable {
private static final long serialVersionUID = 9095736695643670685L;
private Long sourceId;
private String entityName;
private T data;
}
在听众方面,我想以某种方式处理泛型,这就是我尝试过的:
@Slf4j
@Component
@RequiredArgsConstructor
@RabbitListener(queues = MQConfig.WD_COMMONS_QUEUE)
public class WDCommonsListeners {
@RabbitHandler
public void handleA(List<QMessage<Dog>> message) {
System.out.println("handle 1");
}
@RabbitHandler
public void handleB(List<QMessage<Cat>> message) {
System.out.println("handle 2");
}
}
但我收到此异常消息: org.springframework.amqp.AmqpException:负载类型的方法不明确:class java.util.ArrayList:handleA 和 handleB
考虑 Cat 和 Dog class 都在扩展 Animal class
我也尝试过使用未知类型的消息,但我收到了一个对象的 LinkedList:
@RabbitListener(queues = MQConfig.WD_COMMONS_QUEUE)
public void listener(List<QMessage<?>> message) throws IOException {
if (!CollectionUtils.isEmpty(message)) {
for (QMessage<?> msg : message) {
System.out.println("msg");
}
}
也许我必须从消息中获取 JSON 并使用 ObjectMapper 将其转换为对象?
它只是不检查方法参数的通用类型:methodParameter.getParameterType().isAssignableFrom(payloadClass)
。所以,这就是你产生歧义的原因。
由于您的逻辑很难处理集合及其深层嵌套的泛型类型,我真的建议使用单个 @RabbitListener
并手动执行相应的路由。
必须为 TypePrecedence.TYPE_ID
配置 DefaultJackson2JavaTypeMapper
以使其在调用侦听器方法之前将传入数据转换为 List<QMessage<?>>
:https://docs.spring.io/spring-amqp/docs/current/reference/html/#Jackson2JsonMessageConverter-from-message