Spring - 在RabbitMQ侦听器中验证传入消息

时间:2017-11-20 14:39:20

标签: java spring validation spring-mvc rabbitmq

我正在使用spring boot框架,我想通过RabbitMQ将服务中的对象发送到另一个服务:

服务A:

rabbitTemplate.convertAndSend("queue", CreateAccountRequestMessage);

服务B:

@RabbitListener(queues = "queue")
public void onAccountRequested(@Valid CreateAccountRequestMessage createAccountRequestMessage, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG, long tag) throws IOException
{

}

CreateAccountRequestMessage类中,我定义了一些验证注释,如@NotEmpty@NotNull等...但是当我从服务A向服务B发送错误消息时,{{1}在调用@Valid方法

之前,注释不起作用且CreateAccountRequestMessage对象未验证

2 个答案:

答案 0 :(得分:3)

您需要在DefaultMessageHandlerMethodFactory

中设置验证器
@Autowired
SmartValidator validator;

@Bean
public DefaultMessageHandlerMethodFactory messageHandlerMethodFactory() {
    DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
    factory.setValidator(this.validator);
    return factory;
}

然后你还需要指定@Payload注释和@Valid注释。

@RabbitListener(queues = "queue")
public void onAccountRequested(@Valid @Payload CreateAccountRequestMessage 
createAccountRequestMessage, Channel channel, 
@Header(AmqpHeaders.DELIVERY_TAG, long tag) throws IOException
{

}

现在将抛出MethodArgumentNotValidException并丢弃Message,或者您可以将消息发送到死信交换。

答案 1 :(得分:1)

我遇到了同样的问题。除了 SmartValidator,@Praveer 的答案效果很好。我在这里发布了我的解决方案,其灵感来自这篇文章 https://blog.trifork.com/2016/02/29/spring-amqp-payload-validation/

@Configuration
@EnableRabbit
@Slf4j
public class CmsMQConfig implements RabbitListenerConfigurer {

    @Value("${dw.rabbitmq.hosts}")
    private String hosts;

    @Value("${dw.rabbitmq.username}")
    private String username;

    @Value("${dw.rabbitmq.password}")
    private String password;

    @Value("${dw.rabbitmq.virtual-host}")
    private String virtualHost;

    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setMessageConverter(messageConverter());
        return factory;
    }

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(hosts);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        return connectionFactory;
    }

    @Bean
    public Jackson2JsonMessageConverter messageConverter() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JodaModule());
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return new Jackson2JsonMessageConverter(mapper);
    }

    @Bean
    public DefaultMessageHandlerMethodFactory defaultHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        factory.setValidator(amqpValidator());
        return factory;
    }

    @Bean
    public Validator amqpValidator() {
        return new OptionalValidatorFactoryBean();
    }

    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setContainerFactory(rabbitListenerContainerFactory());
        registrar.setMessageHandlerMethodFactory(defaultHandlerMethodFactory());
    }
}