在 Spring 中验证 JMS 负载

Validating JMS payload in Spring

我有一个发送电子邮件的简单服务。可以使用 REST 和 JMS API 调用它。我希望在处理之前验证请求。

当我使用 REST 调用它时,我可以看到 org.springframework.validation.DataBinder 调用了 void validate(Object target, Errors errors, Object... validationHints),然后调用了来自 Hibernate 的验证器。这按预期工作。

问题是我无法使用 JMS Listener 达到相同的效果。监听器实现如下:

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import our.domain.mailing.Mailing;
import our.domain.mailing.jms.api.SendEmailFromTemplateRequest;
import our.domain.mailing.jms.api.SendSimpleEmailRequest;
import javax.validation.Valid;

@ConditionalOnProperty("jms.configuration.destination")
@Component
@AllArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class SendMailMessageListener {
    Mailing mailing;

    @JmsListener(destination = "${jms.configuration.destination}")
    public void sendEmailUsingTemplate(@Valid SendEmailFromTemplateRequest request) {
        log.debug("Received jms message: {}", request);
        mailing.sendEmailTemplate(
                request.getEmailDetails().getRecipients(),
                request.getEmailDetails().getAccountType(),
                request.getTemplateDetails().getTemplateCode(),
                request.getTemplateDetails().getLanguage(),
                request.getTemplateDetails().getParameters());
    }

    @JmsListener(destination = "${jms.configuration.destination}")
    public void sendEmail(@Valid SendSimpleEmailRequest request) {
        log.debug("Received jms message: {}", request);
        mailing.sendEmail(
                request.getRecipients(),
                request.getSubject(),
                request.getMessage());
    }
}

这些方法接收有效载荷但未经过验证。它是 Spring 引导应用程序,我添加了 @EnableJms。您能否指导 Spring 源代码的哪一部分负责发现 @Validate 并处理它?如果您对如何制作有任何提示运行,我将不胜感激。

解决方法很简单,在官方文档中有清楚的描述:29.6.3 Annotated endpoint method signature。您需要做的事情很少:

  1. 提供实现 JmsListenerConfigurer 的配置(添加 @Configuration class 实现此接口)
  2. 在此配置的顶部添加注释@EnableJms
  3. 创建 bean DefaultMessageHandlerMethodFactory。可以在这个配置下完成
  4. 通过您的配置实现接口 JmsListenerConfigurer 的方法 void configureJmsListeners(JmsListenerEndpointRegistrar registrar),并使用您刚刚创建的 bean 设置 MessageHandlerMethodFactory
  5. @Validated 而不是 @Valid 添加到负载参数

您可以在监听器中使用@Valid。您的回答非常接近。在创建 DefaultMessageHandlerMethodFactory 的步骤中调用 .setValidator(validator),其中验证器来自 org.springframework.validation。您可以像这样配置验证器:

@Bean
public LocalValidatorFactoryBean configureValidator ()
{
    return new LocalValidatorFactoryBean();
}

然后将验证器实例注入您的 jms 配置