Java 将SqsListener与SNS和SQS一起使用
我使用的是从AWS的简单队列服务(SQS)接收AWS SNS HTTP通知 以下是侦听器的代码:Java 将SqsListener与SNS和SQS一起使用,java,spring,amazon-web-services,spring-cloud,spring-cloud-aws,Java,Spring,Amazon Web Services,Spring Cloud,Spring Cloud Aws,我使用的是从AWS的简单队列服务(SQS)接收AWS SNS HTTP通知 以下是侦听器的代码: @SqsListener(value = "my-queue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS) public void handle(final MyObject obj) throws Exception { // ... } 上面链接的文档只是关于向队列发送和读取普通序列化对象的,我认为接收SNS消息应该是开箱即用的
@SqsListener(value = "my-queue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void handle(final MyObject obj) throws Exception {
// ...
}
上面链接的文档只是关于向队列发送和读取普通序列化对象的,我认为接收SNS消息应该是开箱即用的。但我最终收到了转换错误:
10:45:51.480[simpleMessageListenerContainer-2]错误
o、 s.c.a.m.l.SimpleMessageListenerContainer-遇到异常
在处理消息时。
org.springframework.MessagingException:异常
调用处理程序方法时发生;嵌套异常是
org.springframework.messaging.converter.MessageConversionException:否
找到要转换为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的
消息
部分被提取并转换为MyObject
,这在没有@NotificationMessage
的情况下也可以工作。这样,您就不需要发送处理此注释所需的“类型”和“消息”部分
首先创建一个具有所需属性的类
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());
}
POJO构造函数中的
@JsonProperty(“MyTask”)
注释可以是可选的,这取决于您的spring版本以及您的属性是否与Json字符串中的名称相同。例如,如果您的属性名为task
,Json字符串名为{“task”:“我的任务”}
您如何能够从SQS接收字符串形式的对象?SQS只支持字符串作为消息,这不是真的吗?@jtcotton63这是真的。负载以String
-一个JSON对象的形式出现,@NotificationMessage
调用一个转换器,该转换器将负载转换为所需类的对象。添加到这个答案中,对我来说,简单地添加@NotificationMessage注释没有帮助,因为我用自己的ArgumentResolver覆盖了QueueMessageHandlerFactory。这对于许多人来说都是如此,因为这是定制Jackson mapper所必需的。在这种情况下,必须更改解析器:fromfactory.setArgumentResolver(List.of(new PayloadArgumentResolver(jacksonMessageConverter))代码>到工厂.setArgumentResolver(新NotificationMessageArgumentResolver(jacksonMessageConverter))的列表代码>但问题是关于接收SNS消息,其中类型
和消息
是它的一部分,这是很久以前的事了,但据我所记得的,消息
被映射到POJO,类型
信息是标题的一部分。我的答案与接受的答案完全相同,但没有使用@NotificationMessage
注释,这在我的情况下会导致其他解析问题。JSON的东西只是一种奖励。
{"MyTask":"My task"}