【问题标题】:Spring integration http rest api call flow understandingSpring集成http rest api调用流程理解
【发布时间】:2022-11-29 23:45:50
【问题描述】:
<int:publish-subscribe-channel id="validateChannel" apply-sequence="true">
        <int:interceptors>
            <int:wire-tap channel="validateLogger" />
        </int:interceptors>
    </int:publish-subscribe-channel>
    <int:logging-channel-adapter id="validateLogger" level="INFO" />

    <int:bridge input-channel="validateChannel" output-channel="validateRequestOutputChannel" />

    <int:bridge input-channel="validateChannel" output-channel="externalServiceChannel" />
    <int:channel id="externalServiceChannel" />

我有 PublishSubscribeChannel 和两个顺序订阅者。有对 2 个外部 API 的调用。

第 1 步(调用第一个外部 api),此 api 将抛出异常或发送 200 OK,如果此 api 抛出 200 ok 或抛出异常,我想调用第二个外部 api(第 2 步),我想捕获它并抛出自定义最终用户例外。

<int:service-activator input-channel="validateRequestOutputChannel" ref="sampleTransformer" method="preprocessRequest" output-channel="testServiceRequestChannel"/>
        <int-http:outbound-gateway id="testService"
            url-expression="headers.testServiceURL"
            http-method="POST" request-channel="testServiceRequestChannel" reply-channel="testResponseChannel"
            charset="UTF-8"
            extract-request-payload="true" expected-response-type="java.lang.String"
            request-factory="customHttpRequestFactory"
                                   mapped-request-headers="Content-Type:application/json"
            reply-timeout="5000">
            <int-http:request-handler-advice-chain>
                <bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
                    <property name="onSuccessExpressionString" value="payload.delete()" />
                    <property name="successChannel" ref="afterSuccessFetchChannel" />
                    <property name="failureChannel" ref="afterFailFetchChannel" />
                    <property name="onFailureExpressionString" value="payload + ' was bad, with reason: ' + #exception.cause.message" />
                </bean>
            </int-http:request-handler-advice-chain>
        </int-http:outbound-gateway>

<int:transformer input-channel="afterSuccessFetchChannel" output-channel="goodResultChannel1"
                     expression="'Fetching service : ' + payload + ' details was successful'" />

    <int:transformer input-channel="afterFailFetchChannel" output-channel="badResultChannel1" ref="exceptionTransformer" method="handleErrorResponse"/>
    <int:logging-channel-adapter id="badResultChannel1" level="ERROR"/>

    <int:logging-channel-adapter id="goodResultChannel1" level="INFO" />

在中间,对于第 2 步,我使用输入通道作为 externalServiceChannel,它是发布子通道的订阅通道,但我无法弄清楚如何将第 1 步的输出通道连接到第 2 步的输入通道,

我试图使用,

<int:exception-type-router input-channel="testResponseChannel" default-output-channel="errorRecoveryChannel">
        <int:mapping exception-type="org.springframework.web.client.HttpClientErrorException.Conflict"
                     channel="lockServiceErrors"/>
    </int:exception-type-router>

    <int:chain input-channel="lockServiceErrors" output-channel="validateOutputChannel">
        <int:header-enricher>
            <int:header name="http_statusCode" value="409" />
        </int:header-enricher>
        <int:transformer expression="payload.failedMessage" />
    </int:chain>

但上面的问题是

  1. 第一个 api 发送 200 Ok,它在消息中发送它的响应负载(我不想要,我想重新使用来自 pub 子频道的那个)
  2. 我尝试使用 ignoreFailures = true,然后在出现异常的情况下,它会抑制来自第一个 api 的异常并继续处理第二个 api,但我想处理异常(它甚至不从异常转换器调用方法)。
  3. 我试过&lt;property name="onSuccessExpressionString" value="payload.delete()" /&gt;,但看起来它并没有真正删除负载。

    能否请你帮忙?

    第 2 步(调用第二个外部 api):

    <int:chain id="test-chain" input-channel="externalServiceChannel" output-channel="validateOutputChannel">
            <int:transformer ref="sampleTransformer" method="preprocessAPIInfo" />
            <int-http:outbound-gateway id="testService2"
                url-expression="headers.testService2URL"
                http-method="GET"
                extract-request-payload="false"
                expected-response-type="com.bibo.test.UserInfo"
                charset="UTF-8"
                request-factory="customHttpRequestFactory"
                mapped-request-headers="Content-Type:application/json,Accept:application/json"
                reply-timeout="5000">
                <int-http:uri-variable name="userId" expression="headers.userId" />
            </int-http:outbound-gateway>
            <int:transformer ref="sampleTransformer" method="processUserInfo" />
            <int:object-to-json-transformer/>
        </int:chain>
    

【问题讨论】:

    标签: spring-integration spring-integration-http


    【解决方案1】:

    我建议您在没有发布-订阅渠道的情况下修改您的流程,但真正使其线性化:在第一个服务之后调用第二个服务。如果第一步失败,它不会进入第二步,而第二步实际上是第一步的输出。

    要在第二步中保留原始请求访问权限,有一个技巧:将此请求放入标头中:

    <int:header-enricher>
        <int:header name="originalRequest" expression="payload"/>
    </int:header-enricher>
    

    然后当你在第二步需要它时,你只需这样做:

    <int:transformer expression="headers.originalRequest"/>
    

    其余的错误处理逻辑可能没问题。

    【讨论】:

    • 非常感谢您的意见!但我对第 2 步调用第二个外部 api 的输入通道应该是什么感到困惑?而且您是否认为需要异常类型路由器,因为我也在尝试使用 ExpressionEvaluatingRequestHandlerAdvice?
    • 第二步的输入通道是第一步的输出。您可以将这些步骤分成链并通过通道连接它们。如果第一个链失败,则不会调用第二个。为第二步提取原始有效载荷可以作为第一链中的最后一个动作。是的,ExpressionEvaluatingRequestHandlerAdvice 可用于处理第一次服务调用的错误。路由器可以作为该错误处理逻辑的一部分。
    猜你喜欢
    • 2021-07-09
    • 2016-03-02
    • 2016-06-09
    • 2019-08-04
    • 2018-06-22
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多