Spring 集成 + 过滤器 + 向 REST 控制器发送 400 错误请求

Spring Integration + filter + send a 400 bad request to REST controller

我有一个 REST 控制器 class,它调用消息网关并发送要由 Spring 集成流程处理的订单:

@MessagingGateway
public interface OrderGateway {

    @Gateway(requestChannel = "orders.input")
    void processOrderRequest(Order order);

}

如果订单有效,则向kafka发送2个事件。如果订单无效,将向 kafka 发送一个 "rejected" 事件,并将一个 400 Bad 请求发送回 REST 控制器 class,以便用户知道请求有问题。

除了向控制器发回 400 Bad 请求的部分外,我已经能够使此流程正常工作。

以下是我到目前为止成功将事件发送到 kafka 的内容:

@Bean
public IntegrationFlow orders(KafkaTemplate<?, ?> kafkaTemplate) {
    return f -> f
            .<Order> filter(request -> orderValidator.isValid(request), fs -> fs.discardFlow(
                    df -> df
                            .transform(orderRejectedEventTransformer)
                            .handle( m -> Kafka.outboundChannelAdapter(kafkaTemplate).messageKey(this.properties.getMessageKey()) )
            ))
            .publishSubscribeChannel(s -> s
                    .subscribe(fl -> fl
                            .transform(orderReceivedEventTransformer)
                            .handle(  Kafka.outboundChannelAdapter(kafkaTemplate).messageKey(this.properties.getMessageKey()) )
                    )
                    .subscribe(fl -> fl
                            .transform(orderSuccessfulEventTransformer)
                            .handle( Kafka.outboundChannelAdapter(kafkaTemplate).messageKey(this.properties.getMessageKey()) )
                    )
            );
}

我想我必须在某处抛出异常,但我完全不知道如何发送错误的请求响应。

提前致谢。

Spring MVC 带有一些默认配置,其中一部分是异常处理。在 WebMvcConfigurationSupport:

中看起来像这样
/**
 * A method available to subclasses for adding default
 * {@link HandlerExceptionResolver HandlerExceptionResolvers}.
 * <p>Adds the following exception resolvers:
 * <ul>
 * <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
 * {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
 * <li>{@link ResponseStatusExceptionResolver} for exceptions annotated with
 * {@link org.springframework.web.bind.annotation.ResponseStatus}.
 * <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring exception types
 * </ul>
 */
protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers,
        ContentNegotiationManager mvcContentNegotiationManager) {

您可能没有任何 @ExceptionHandler,您也可能不会使用 @ResponseStatus 抛出自定义异常,但 DefaultHandlerExceptionResolver 可能会为您解决问题。

要将 400 Bad request 发送回客户端,您需要抛出 HttpMessageNotReadableException

当被拒绝时,你必须与 .handle() 并行地向 Kafka 抛出这样的异常。我的意思是 publishSubscribeChannel() 应该很适合这里。

阿尔乔姆,

当你说与.handle并行抛出异常时,你的意思是这样的:

@Bean
public IntegrationFlow orders(KafkaTemplate<?, ?> kafkaTemplate) {
    return f -> f
            .<Order> filter(request -> orderValidator.isValid(request), fs -> fs.discardFlow(
                    df -> df
                    .publishSubscribeChannel(s -> s
                            .subscribe(fl -> fl
                                    .transform(orderRejectedEventTransformer)
                                    .handle(  Kafka.outboundChannelAdapter(kafkaTemplate).messageKey(this.properties.getMessageKey()) )
                            )
                            .subscribe(fl -> fl
                                    .handle(  handleException() )
                            )
                    )
            ))
            .publishSubscribeChannel(s -> s
                    .subscribe(fl -> fl
                            .transform(orderReceivedEventTransformer)
                            .handle(  Kafka.outboundChannelAdapter(kafkaTemplate).messageKey(this.properties.getMessageKey()) )
                    )
                    .subscribe(fl -> fl
                            .transform(orderSuccessfulEventTransformer)
                            .handle( Kafka.outboundChannelAdapter(kafkaTemplate).messageKey(this.properties.getMessageKey()) )
                    )
            );
}

    public void handleException() throws Exception {
        throw new HttpMessageNotReadableException("bad request");
    }

我能够让它工作,我的意思是发送 400 Bad 请求,但我确实必须做这样的事情

.handle(  exceptionService ) //injected bean

@Component
public class ExceptionService {
    public void handleException() throws Exception {
        throw new HttpMessageNotReadableException("bad request");
    }
}

我无法在 .handle 方法中直接调用 handleException() 方法,因为它抛出了异常。不确定如何处理它,所以我不得不创建该组件,但不太喜欢它。

我想知道在消息网关上有一个 replyChannel 是否是从 Spring 集成流向其余控制器发回响应的方式。