将 SqsListener 与 SNS 和 SQS 结合使用

Using SqsListener with SNS and SQS

我正在使用来自 AWS 的简单队列服务 (SQS) 的 spring-cloud-aws's SqsListener to receive AWS SNS HTTP Notifications in JSON Format

这是侦听器的代码:

@SqsListener(value = "my-queue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void handle(final MyObject obj) throws Exception {
// ...
}

上面链接的文档只是关于向队列发送和读取普通序列化对象,我认为接收 SNS 消息应该是开箱即用的。但我最终收到转换错误:

10:45:51.480 [simpleMessageListenerContainer-2] ERROR o.s.c.a.m.l.SimpleMessageListenerContainer - Exception encountered while processing message. org.springframework.messaging.MessagingException: An exception occurred while invoking the handler method; nested exception is org.springframework.messaging.converter.MessageConversionException: No converter found to convert to class com.myproject.model.MyObject, message=GenericMessage

我还尝试创建一个包装器对象,它看起来像上面链接的预期 SNS Json 格式,但我总是遇到同样的异常。唯一有效的类型是签名中的字符串。 SNS不应该自动转换吗?

是的,它应该。它确实如此。

为了在反序列化时调用正确的 HandlerMethodArgumentResolver(在本例中为 NotificationMessageArgumentResolver),进而调用正确的转换器 NotificationRequestConverter,您只需添加注释 org.springframework.cloud.aws.messaging.config.annotation.NotificationMessage 添加到您的方法签名中。例如

@SqsListener(value = "my-queue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void handle(final @NotificationMessage MyObject obj) throws Exception {
// ...
}

这样,您的 SNS 的 Message 部分将被提取并转换为 MyObject

这在没有 @NotificationMessage 的情况下也有效。这样您就不需要发送 "Type" 和 "Message" 部分,这是使用此注释所必需的。

首先创建一个具有所需属性的 class。

public class SqsMessage {

   private String myTask;

   public SqsMessage() {
   }

   public SqsMessage(@JsonProperty("MyTask") String myTask ) {
       this.myTask = myTask ;
   }

   //Getter + Setter 
}

接下来设置监听器

@SqsListener(value = {"MyQueue"}, deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void receiveMessage(SqsMessage payload, @Headers Map<String, Object> header) {
   logger.info("Got message with task: " + payload.getTask() 
    + " with custom attribute " + header.get("CustomAttribute").toString());
}

现在您可以发送 JSON 赞

{"MyTask":"My task"}

POJO 构造函数中的 @JsonProperty("MyTask") 注释可以是可选的,具体取决于您的 spring 版本以及您的属性是否与 Json 字符串中的名称相同。例如,如果您的属性名为 task 并且您的 Json 字符串为 {"task":"My task"}.

,则没有必要