2

我正在为 AWS SQS 编写一些消息使用者,并希望使用 javax.validation.constraints 注释来验证接收到的消息。不幸的是,我不得不发现 spring-cloud-aws-messaging 依赖项使用的 PayloadArgumentResolver 使用了 NoOpValidator。所以我尝试为有效负载注入我自己的 HandlerMethodArgumentResolver。

  @Bean
  public QueueMessageHandlerFactory queueMessageHandlerFactory(
      final ObjectMapper objectMapper, final Validator hibernateValidator) {
    final MappingJackson2MessageConverter jacksonMessageConverter =
        new MappingJackson2MessageConverter();
    jacksonMessageConverter.setSerializedPayloadClass(String.class);
    jacksonMessageConverter.setStrictContentTypeMatch(true);
    jacksonMessageConverter.setObjectMapper(objectMapper);
    final QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory();

    final List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>();
    argumentResolvers.add(new HeaderMethodArgumentResolver(null, null));
    argumentResolvers.add(new HeadersMethodArgumentResolver());

    argumentResolvers.add(new NotificationSubjectArgumentResolver());
    argumentResolvers.add(new AcknowledgmentHandlerMethodArgumentResolver("Acknowledgment"));
    argumentResolvers.add(new VisibilityHandlerMethodArgumentResolver("Visibility"));

    final PayloadArgumentResolver payloadArgumentResolver =
        new PayloadArgumentResolver(jacksonMessageConverter, hibernateValidator);
    argumentResolvers.add(payloadArgumentResolver);

    factory.setArgumentResolvers(argumentResolvers);
    return factory;
  }

到目前为止一切顺利,乍一看,它运行良好......但正如你所见,我还必须添加已经存在于 QueueMessageHandler 中的参数解析器,以通过消息的 @Headers/@Header 解析标题。

  @SqsListener(
      value = "queue",
      deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
  public void consume(
      @Payload @Validated final QueueMessage queueMessage,
      @Headers final Map<String,Object> headers) {
  }

当我只添加带有休眠验证器的 PayloadArgumentResolver 时,它也将用于解析标头,doh!

有没有什么漂亮的解决方案,或者我应该在 spring-cloud-aws 上打开一个问题?我只想通过注释验证我的有效负载:(

4

1 回答 1

0

我认为这不是最好的 awswer,但我有一个具有此类验证的工作示例项目:https ://github.com/Haple/sqslistener

@Data
@RequiredArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)
public class EventDTO {

  @NotNull(message = "foo is mandatory")
  private final String foo;

  @NotNull(message = "bar is mandatory")
  private final String bar;

}

@Slf4j
@Service
@AllArgsConstructor
public class SampleListener {

  @SqsListener("test_queue")
  public void execute(final @Valid @Payload EventDTO event) {
    log.info("OK: {}", event);
  }

}
@Configuration
public class MessageHandler {
  @Bean
  QueueMessageHandler queueMessageHandler(final AmazonSQSAsync amazonSQSAsync,
      final MessageConverter messageConverter,
      final Validator validator) {
    final QueueMessageHandlerFactory queueMessageHandlerFactory = new QueueMessageHandlerFactory();
    final PayloadMethodArgumentResolver payloadMethodArgumentResolver = new PayloadMethodArgumentResolver(messageConverter, validator);
    queueMessageHandlerFactory.setArgumentResolvers(Collections.singletonList(payloadMethodArgumentResolver));
    queueMessageHandlerFactory.setAmazonSqs(amazonSQSAsync);
    queueMessageHandlerFactory.setMessageConverters(Collections.singletonList(messageConverter));
    return queueMessageHandlerFactory.createQueueMessageHandler();
  }
}
于 2020-12-18T20:37:21.700 回答