HTTP 名稱空間支援

Spring Integration 提供了一個 http 名稱空間和相應的 schema 定義。要將其包含在您的配置中,請在您的應用程式上下文配置檔案中提供以下名稱空間宣告:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"
  xmlns:int-http="http://www.springframework.org/schema/integration/http"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration
    https://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/http
    https://www.springframework.org/schema/integration/http/spring-integration-http.xsd">
    ...
</beans>

入站

XML 名稱空間提供了兩個用於處理 HTTP 入站請求的元件:inbound-channel-adapterinbound-gateway。要處理不返回專用響應的請求,請使用 inbound-channel-adapter。以下示例展示瞭如何配置一個:

<int-http:inbound-channel-adapter id="httpChannelAdapter" channel="requests"
    supported-methods="PUT, DELETE"/>

要處理預期響應的請求,請使用 inbound-gateway。以下示例展示瞭如何配置一個:

<int-http:inbound-gateway id="inboundGateway"
    request-channel="requests"
    reply-channel="responses"/>

請求對映支援

Spring Integration 3.0 透過引入 IntegrationRequestMappingHandlerMapping 改進了 REST 支援。該實現依賴於 Spring Framework 3.1 或更高版本提供的增強型 REST 支援。

HTTP 入站閘道器或 HTTP 入站通道介面卡的解析會註冊一個型別為 IntegrationRequestMappingHandlerMappingintegrationRequestMappingHandlerMapping bean,如果尚未註冊的話。此 HandlerMapping 的特定實現將其邏輯委託給 RequestMappingInfoHandlerMapping。該實現提供了與 Spring MVC 中 org.springframework.web.bind.annotation.RequestMapping 註解類似的功能。

有關更多資訊,請參閱 使用 @RequestMapping 對映請求

為此,Spring Integration 3.0 引入了 <request-mapping> 元素。您可以將此可選元素新增到 <http:inbound-channel-adapter><http:inbound-gateway>。它與 pathsupported-methods 屬性協同工作。以下示例展示瞭如何在入站閘道器上配置它:

<inbound-gateway id="inboundController"
    request-channel="requests"
    reply-channel="responses"
    path="/foo/{fooId}"
    supported-methods="GET"
    view-name="foo"
    error-code="oops">
   <request-mapping headers="User-Agent"
     params="myParam=myValue"
     consumes="application/json"
     produces="!text/plain"/>
</inbound-gateway>

基於上述配置,名稱空間解析器會建立一個 IntegrationRequestMappingHandlerMapping 例項(如果不存在),以及一個 HttpRequestHandlingController bean,併為其關聯一個 RequestMapping 例項。此 RequestMapping 例項又會轉換為 Spring MVC 的 RequestMappingInfo

<request-mapping> 元素提供以下屬性:

  • headers

  • params

  • consumes

  • produces

<http:inbound-channel-adapter><http:inbound-gateway>pathsupported-methods 屬性一起,<request-mapping> 屬性直接轉換為 Spring MVC 中 org.springframework.web.bind.annotation.RequestMapping 註解提供的相應選項。

<request-mapping> 元素允許您將多個 Spring Integration HTTP 入站端點配置到相同的 path(甚至相同的 supported-methods),並允許您根據傳入的 HTTP 請求提供不同的下游訊息流。

或者,您也可以只宣告一個 HTTP 入站端點,並在 Spring Integration 流中應用路由和過濾邏輯以實現相同的結果。這使得您能夠儘快將 Message 引入流中。以下示例展示瞭如何實現:

<int-http:inbound-gateway request-channel="httpMethodRouter"
    supported-methods="GET,DELETE"
    path="/process/{entId}"
    payload-expression="#pathVariables.entId"/>

<int:router input-channel="httpMethodRouter" expression="headers.http_requestMethod">
    <int:mapping value="GET" channel="in1"/>
    <int:mapping value="DELETE" channel="in2"/>
</int:router>

<int:service-activator input-channel="in1" ref="service" method="getEntity"/>

<int:service-activator input-channel="in2" ref="service" method="delete"/>

有關處理程式對映的更多資訊,請參閱 Spring Framework Web Servlet 文件Spring Framework Web Reactive 文件

IntegrationRequestMappingHandlerMapping 擴充套件了 Spring MVC 的 RequestMappingHandlerMapping 類,繼承了其大部分邏輯,特別是 handleNoMatch(Set, String, HttpServletRequest),當對映因某種原因不匹配時,它會丟擲 HTTP 響應的特定 4xx 錯誤,從而阻止呼叫應用程式上下文中任何剩餘的對映處理程式。因此,不支援為 Spring Integration 和 Spring MVC 請求對映配置相同的路徑(例如,一個為 POST,另一個為 GET);MVC 對映將找不到。

跨域資源共享 (CORS) 支援

從版本 4.2 開始,您可以使用 <cross-origin> 元素配置 <http:inbound-channel-adapter><http:inbound-gateway>。它代表與 Spring MVC 的 @CrossOrigin 對於 @Controller 註解相同的選項,並允許為 Spring Integration HTTP 端點配置跨域資源共享 (CORS):

  • origin: 允許的來源列表。* 表示允許所有來源。這些值放置在預檢和實際響應的 Access-Control-Allow-Origin 頭部中。預設值為 *

  • allowed-headers: 指示在實際請求期間可以使用哪些請求頭部。* 表示允許客戶端請求的所有頭部。此屬性控制預檢響應的 Access-Control-Allow-Headers 頭部的值。預設值為 *

  • exposed-headers: 使用者代理允許客戶端訪問的響應頭部列表。此屬性控制實際響應的 Access-Control-Expose-Headers 頭部的值。

  • method: 允許的 HTTP 請求方法:GETPOSTHEADOPTIONSPUTPATCHDELETETRACE。此處指定的方法會覆蓋 supported-methods 中的方法。

  • allow-credentials: 如果瀏覽器應包含與請求域關聯的任何 cookie,則設定為 true,否則設定為 false。空字串 ("") 表示未定義。如果為 true,則預檢響應包含 Access-Control-Allow-Credentials=true 頭部。預設值為 true

  • max-age: 控制預檢響應的快取持續時間。將其設定為合理的值可以減少瀏覽器所需的預檢請求-響應互動次數。此屬性控制預檢響應中 Access-Control-Max-Age 頭部的值。值 -1 表示未定義。預設值為 1800 秒(30 分鐘)。

CORS Java 配置由 org.springframework.integration.http.inbound.CrossOrigin 類表示,其例項可以注入到 HttpRequestHandlingEndpointSupport bean 中。

響應狀態碼

從版本 4.1 開始,您可以為 <http:inbound-channel-adapter> 配置 status-code-expression 以覆蓋預設的 200 OK 狀態。表示式必須返回一個可轉換為 org.springframework.http.HttpStatus 列舉值的物件。evaluationContext 具有 BeanResolver,並且從版本 5.1 開始,將 RequestEntity<?> 作為根物件提供。一個示例可能是在執行時解析某個範圍 bean,該 bean 返回狀態碼值。然而,最常見的情況是將其設定為固定值,例如 status-code=expression="204" (No Content) 或 status-code-expression="T(org.springframework.http.HttpStatus).NO_CONTENT"。預設情況下,status-code-expression 為 null,這意味著返回正常的“200 OK”響應狀態。使用 RequestEntity<?> 作為根物件,狀態碼可以根據請求方法、某個頭部、URI 內容甚至請求正文進行條件設定。以下示例展示瞭如何將狀態碼設定為 ACCEPTED

<http:inbound-channel-adapter id="inboundController"
       channel="requests" view-name="foo" error-code="oops"
       status-code-expression="T(org.springframework.http.HttpStatus).ACCEPTED">
   <request-mapping headers="BAR"/>
</http:inbound-channel-adapter>

<http:inbound-gateway> 從回覆 Messagehttp_statusCode 頭部解析“狀態碼”。從版本 4.2 開始,在 reply-timeout 內未收到回覆時的預設響應狀態碼是 500 Internal Server Error。有兩種方法可以修改此行為:

  • 新增一個 reply-timeout-status-code-expression。這與入站介面卡上的 status-code-expression 具有相同的語義。

  • 新增一個 error-channel 並返回帶有 HTTP 狀態碼頭部的適當訊息,如以下示例所示:

    <int:chain input-channel="errors">
        <int:header-enricher>
            <int:header name="http_statusCode" value="504" />
        </int:header-enricher>
        <int:transformer expression="payload.failedMessage" />
    </int:chain>

ErrorMessage 的有效負載是 MessageTimeoutException。它必須轉換為可以由閘道器轉換的東西,例如 String。一個好的候選是異常的 message 屬性,這是您使用 expression 技術時使用的值。

如果錯誤流在主流超時後超時,則返回 500 Internal Server Error,或者,如果存在 reply-timeout-status-code-expression,則對其進行評估。

以前,超時的預設狀態碼是 200 OK。要恢復該行為,請設定 reply-timeout-status-code-expression="200"

此外,從版本 5.4 開始,在準備請求訊息時遇到的錯誤將傳送到錯誤通道(如果提供)。關於丟擲適當異常的決定應在錯誤流中透過檢查異常來完成。以前,任何異常都會簡單地丟擲,導致 HTTP 500 伺服器錯誤響應狀態,但在某些情況下,問題可能是由於不正確的請求引數引起的,因此應丟擲帶有 4xx 客戶端錯誤狀態的 ResponseStatusException。有關更多資訊,請參閱 ResponseStatusException。傳送到此錯誤通道的 ErrorMessage 包含原始異常作為有效負載以供分析。

URI 模板變數和表示式

透過將 path 屬性與 payload-expression 屬性和 header 元素結合使用,您可以高度靈活地對映入站請求資料。

在以下示例配置中,入站通道介面卡被配置為使用以下 URI 接受請求:

/first-name/{firstName}/last-name/{lastName}

當您使用 payload-expression 屬性時,{firstName} URI 模板變數對映到 Message 有效負載,而 {lastName} URI 模板變數對映到 lname 訊息頭部,如下例所示:

<int-http:inbound-channel-adapter id="inboundAdapterWithExpressions"
    path="/first-name/{firstName}/last-name/{lastName}"
    channel="requests"
    payload-expression="#pathVariables.firstName">
    <int-http:header name="lname" expression="#pathVariables.lastName"/>
</int-http:inbound-channel-adapter>

有關 URI 模板變數的更多資訊,請參閱 Spring 參考手冊中的 URI 模板模式

自 Spring Integration 3.0 起,除了有效負載和頭部表示式中可用的現有 #pathVariables#requestParams 變數外,我們還添加了其他有用的表示式變數:

  • #requestParams: 來自 ServletRequest parameterMapMultiValueMap

  • #pathVariables: 來自 URI 模板佔位符及其值的 Map

  • #matrixVariables: 根據 Spring MVC 規範MultiValueMapMap。請注意,#matrixVariables 需要 Spring MVC 3.2 或更高版本。

  • #requestAttributes: 與當前請求關聯的 org.springframework.web.context.request.RequestAttributes

  • #requestHeaders: 來自當前請求的 org.springframework.http.HttpHeaders 物件。

  • #cookies: 來自當前請求的 jakarta.servlet.http.Cookie 例項的 MultiValueMap<String, Cookie>

請注意,如果訊息流是單執行緒的且存在於請求執行緒中,則所有這些值(以及其他值)都可以在下游訊息流中的表示式中透過 ThreadLocal org.springframework.web.context.request.RequestAttributes 變數進行訪問。以下示例配置了一個使用 expression 屬性的轉換器:

<int-:transformer
    expression="T(org.springframework.web.context.request.RequestContextHolder).
                  requestAttributes.request.queryString"/>

出站

要配置出站閘道器,您可以使用名稱空間支援。以下程式碼片段顯示了出站 HTTP 閘道器的可用配置選項:

<int-http:outbound-gateway id="example"
    request-channel="requests"
    url="https:///test"
    http-method="POST"
    extract-request-payload="false"
    expected-response-type="java.lang.String"
    charset="UTF-8"
    request-factory="requestFactory"
    reply-timeout="1234"
    reply-channel="replies"/>

最重要的是,請注意提供了“http-method”和“expected-response-type”屬性。這是兩個最常配置的值。預設的 http-methodPOST,預設的響應型別是 null。當響應型別為 null 時,只要 HTTP 狀態是成功(非成功狀態碼會丟擲異常),回覆 Message 的有效負載就包含 ResponseEntity。如果您預期不同的型別,例如 String,請提供其完全限定的類名(在前面的示例中為 java.lang.String)。另請參閱 HTTP 出站元件 中關於空響應體的注意事項。

從 Spring Integration 2.1 開始,HTTP 出站閘道器的 request-timeout 屬性已重新命名為 reply-timeout,以更好地反映其意圖。

自 Spring Integration 2.2 起,HTTP 上的 Java 序列化預設不再啟用。以前,當將 expected-response-type 屬性設定為 Serializable 物件時,Accept 頭部未正確設定。自 Spring Integration 2.2 起,SerializingHttpMessageConverter 已更新為將 Accept 頭部設定為 application/x-java-serialized-object

然而,由於這可能導致與現有應用程式不相容,因此決定不再自動將此轉換器新增到 HTTP 端點。如果您希望使用 Java 序列化,可以透過使用 message-converters 屬性(在使用 XML 配置時)或使用 setMessageConverters() 方法(在 Java 配置中)將 SerializingHttpMessageConverter 新增到適當的端點。或者,您可能希望考慮改用 JSON,透過在類路徑上包含 Jackson 庫 來啟用 JSON。

從 Spring Integration 2.2 開始,您還可以使用 SpEL 和 http-method-expression 屬性動態確定 HTTP 方法。請注意,此屬性與 http-method 互斥。您還可以使用 expected-response-type-expression 屬性代替 expected-response-type 並提供任何有效的 SpEL 表示式來確定響應型別。以下配置示例使用 expected-response-type-expression

<int-http:outbound-gateway id="example"
    request-channel="requests"
    url="https:///test"
    http-method-expression="headers.httpMethod"
    extract-request-payload="false"
    expected-response-type-expression="payload"
    charset="UTF-8"
    request-factory="requestFactory"
    reply-timeout="1234"
    reply-channel="replies"/>

如果您的出站介面卡將以單向方式使用,則可以改用 outbound-channel-adapter。這意味著成功響應執行後不會向回覆通道傳送任何訊息。在任何不成功的響應狀態碼的情況下,它都會丟擲異常。配置看起來與閘道器非常相似,如下例所示:

<int-http:outbound-channel-adapter id="example"
    url="https:///example"
    http-method="GET"
    channel="requests"
    charset="UTF-8"
    extract-payload="false"
    expected-response-type="java.lang.String"
    request-factory="someRequestFactory"
    order="3"
    auto-startup="false"/>

要指定 URL,您可以使用“url”屬性或“url-expression”屬性。“url”屬性接受一個簡單的字串(帶有 URI 變數的佔位符,如下所述)。“url-expression”是一個 SpEL 表示式,以 Message 作為根物件,可實現動態 URL。表示式評估結果的 URL 仍然可以具有 URI 變數的佔位符。

在以前的版本中,一些使用者使用佔位符將整個 URL 替換為 URI 變數。Spring 3.1 的更改可能會導致一些跳脫字元(如“?”)出現問題。因此,我們建議,如果您希望在執行時完全生成 URL,請使用“url-expression”屬性。

對映 URI 變數

如果您的 URL 包含 URI 變數,您可以使用 uri-variable 元素對其進行對映。此元素可用於 HTTP 出站閘道器和 HTTP 出站通道介面卡。以下示例將 zipCode URI 變數對映到一個表示式:

<int-http:outbound-gateway id="trafficGateway"
    url="https://local.yahooapis.com/trafficData?appid=YdnDemo&amp;zip={zipCode}"
    request-channel="trafficChannel"
    http-method="GET"
    expected-response-type="java.lang.String">
    <int-http:uri-variable name="zipCode" expression="payload.getZip()"/>
</int-http:outbound-gateway>

uri-variable 元素定義了兩個屬性:nameexpressionname 屬性標識 URI 變數的名稱,而 expression 屬性用於設定實際值。透過使用 expression 屬性,您可以充分利用 Spring Expression Language (SpEL) 的強大功能,它為您提供了對訊息負載和訊息頭部的完全動態訪問。例如,在前面的配置中,在 Message 的負載物件上呼叫 getZip() 方法,並將該方法的結果用作名為“zipCode”的 URI 變數的值。

自 Spring Integration 3.0 起,HTTP 出站端點支援 uri-variables-expression 屬性,用於指定一個應進行評估的 expression,從而生成 URL 模板中所有 URI 變數佔位符的 Map。它提供了一種機制,您可以使用不同的變量表達式,基於出站訊息。此屬性與 <uri-variable/> 元素互斥。以下示例展示瞭如何使用 uri-variables-expression 屬性:

<int-http:outbound-gateway
     url="https://foo.host/{foo}/bars/{bar}"
     request-channel="trafficChannel"
     http-method="GET"
     uri-variables-expression="@uriVariablesBean.populate(payload)"
     expected-response-type="java.lang.String"/>

uriVariablesBean 可能定義如下:

public class UriVariablesBean {
    private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();

    public Map<String, ?> populate(Object payload) {
        Map<String, Object> variables = new HashMap<String, Object>();
        if (payload instanceOf String.class)) {
            variables.put("foo", "foo"));
        }
        else {
            variables.put("foo", EXPRESSION_PARSER.parseExpression("headers.bar"));
        }
        return variables;
    }

}
uri-variables-expression 必須評估為 MapMap 的值必須是 StringExpression 的例項。此 Map 提供給 ExpressionEvalMap,以便在出站 Message 的上下文中,使用這些表示式進一步解析 URI 變數佔位符。

重要提示 uriVariablesExpression 屬性提供了一個非常強大的機制來評估 URI 變數。我們預計人們大多會使用簡單的表示式,如前面的示例。但是,您也可以配置諸如 "@uriVariablesBean.populate(#root)" 之類的東西,其中返回的對映中的表示式為 variables.put("thing1", EXPRESSION_PARSER.parseExpression(message.getHeaders().get("thing2", String.class)));,其中表達式在名為 thing2 的訊息頭部中動態提供。由於頭部可能來自不受信任的源,HTTP 出站端點在評估這些表示式時使用 SimpleEvaluationContextSimpleEvaluationContext 僅使用 SpEL 功能的子集。如果您信任您的訊息源並希望使用受限制的 SpEL 構造,請將出站端點的 trustedSpel 屬性設定為 true

您可以透過使用自定義 url-expression 和一些用於構建和編碼 URL 引數的實用程式來實現需要按訊息提供一組動態 URI 變數的場景。以下示例展示瞭如何實現:

url-expression="T(org.springframework.web.util.UriComponentsBuilder)
                           .fromHttpUrl('https://HOST:PORT/PATH')
                           .queryParams(payload)
                           .build()
                           .toUri()"

queryParams() 方法期望一個 MultiValueMap<String, String> 作為引數,因此您可以在執行請求之前預先構建一組真實的 URL 查詢引數。

整個 queryString 也可以表示為 uri-variable,如下例所示:

<int-http:outbound-gateway id="proxyGateway" request-channel="testChannel"
              url="http://testServer/test?{queryString}">
    <int-http:uri-variable name="queryString" expression="'a=A&amp;b=B'"/>
</int-http:outbound-gateway>

在這種情況下,您必須手動提供 URL 編碼。例如,您可以使用 org.apache.http.client.utils.URLEncodedUtils#format() 來實現此目的。如前所述,手動構建的 MultiValueMap<String, String> 可以使用以下 Java Streams 程式碼片段轉換為 List<NameValuePair> format() 方法引數:

List<NameValuePair> nameValuePairs =
    params.entrySet()
            .stream()
            .flatMap(e -> e
                    .getValue()
                    .stream()
                    .map(v -> new BasicNameValuePair(e.getKey(), v)))
            .collect(Collectors.toList());

控制 URI 編碼

預設情況下,URL 字串在傳送請求之前會編碼(參見 UriComponentsBuilder)為 URI 物件。在某些非標準 URI(例如 RabbitMQ REST API)的場景中,執行編碼是不希望的。<http:outbound-gateway/><http:outbound-channel-adapter/> 提供了一個 encoding-mode 屬性。要停用 URL 編碼,請將此屬性設定為 NONE(預設情況下,它是 TEMPLATE_AND_VALUES)。如果您希望部分編碼 URL 的某些部分,請在 <uri-variable/> 中使用 expression,如下例所示:

<http:outbound-gateway url="https://somehost/%2f/fooApps?bar={param}" encoding-mode="NONE">
          <http:uri-variable name="param"
            expression="T(org.apache.commons.httpclient.util.URIUtil)
                                             .encodeWithinQuery('Hello World!')"/>
</http:outbound-gateway>

對於 Java DSL,此選項可以透過 BaseHttpMessageHandlerSpec.encodingMode() 選項進行控制。相同的配置也適用於 WebFlux 模組Web Services 模組 中的類似出站元件。對於更復雜的場景,建議在外部提供的 RestTemplate 上配置 UriTemplateHandler;或者對於 WebFlux,使用 WebClient 及其 UriBuilderFactory

© . This site is unofficial and not affiliated with VMware.