HTTP Namespace Support
Spring Integration 提供了一个 http
命名空间和相应的架构定义。要在您的配置中包含它,请在您的应用程序上下文配置中提供以下命名空间声明:
Spring Integration provides an http
namespace and the corresponding schema definition.
To include it in your configuration, provide the following namespace declaration in your application context configuration file:
<?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>
Inbound
XML 命名空间提供了用于处理 HTTP 入站请求的两个组件:inbound-channel-adapter
和 inbound-gateway
。为了在不返回专用响应的情况下处理请求,请使用 inbound-channel-adapter
。以下示例显示如何配置其中一个:
The XML namespace provides two components for handling HTTP inbound requests: inbound-channel-adapter
and inbound-gateway
.
In order to process requests without returning a dedicated response, use the inbound-channel-adapter
.
The following example shows how to configure one:
<int-http:inbound-channel-adapter id="httpChannelAdapter" channel="requests"
supported-methods="PUT, DELETE"/>
要处理需要响应的请求,请使用 inbound-gateway
。以下示例显示如何配置其中一个:
To process requests that do expect a response, use an inbound-gateway
.
The following example shows how to configure one:
<int-http:inbound-gateway id="inboundGateway"
request-channel="requests"
reply-channel="responses"/>
Request Mapping Support
Spring Integration 3.0 通过引入 link:https://docs.spring.io/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html[ |
Spring Integration 3.0 improved the REST support by introducing the |
HTTP 入站网关或 HTTP 入站通道适配器的解析会注册一个类型为 IntegrationRequestMappingHandlerMapping
的 integrationRequestMappingHandlerMapping`bean,如果尚未注册该 bean。 `HandlerMapping
的此特定实现将其逻辑委派给 RequestMappingInfoHandlerMapping
。该实现提供的功能类似于 Spring MVC 中的 org.springframework.web.bind.annotation.RequestMapping
注解。
The parsing of the HTTP inbound gateway or the HTTP inbound channel adapter registers an integrationRequestMappingHandlerMapping
bean of type IntegrationRequestMappingHandlerMapping
, in case one is not yet registered.
This particular implementation of the HandlerMapping
delegates its logic to RequestMappingInfoHandlerMapping
.
The implementation provides functionality similar to the org.springframework.web.bind.annotation.RequestMapping
annotation in Spring MVC.
有关详细信息,请参阅 link:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping[Mapping Requests With |
For more information, see Mapping Requests With |
为此,Spring Integration 3.0 引入了 <request-mapping>
元素。您可以在 <http:inbound-channel-adapter>
和 <http:inbound-gateway>
中添加此可选元素。它与 path
和 supported-methods
属性配合使用。以下示例显示如何将其配置在入站网关上:
For this purpose, Spring Integration 3.0 introduces the <request-mapping>
element.
You can add this optional element to <http:inbound-channel-adapter>
and <http:inbound-gateway>
.
It works in conjunction with the path
and supported-methods
attributes.
The following example shows how to configure it on an inbound gateway:
<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
。
Based on the preceding configuration, the namespace parser creates an instance of the IntegrationRequestMappingHandlerMapping
(if none exists) and an HttpRequestHandlingController
bean and associates with it an instance of RequestMapping
.
This RequestMapping
instance is, in turn, converted to the Spring MVC RequestMappingInfo
.
<request-mapping>
元素提供了以下属性:
The <request-mapping>
element provides the following attributes:
-
headers
-
params
-
consumes
-
produces
对于 <http:inbound-channel-adapter>
或 <http:inbound-gateway>
的 path
和 supported-methods
属性,<request-mapping>
属性直接转换为 Spring MVC 中 org.springframework.web.bind.annotation.RequestMapping
注解提供的相应选项。
With the path
and supported-methods
attributes of the <http:inbound-channel-adapter>
or the <http:inbound-gateway>
, <request-mapping>
attributes translate directly into the respective options provided by the org.springframework.web.bind.annotation.RequestMapping
annotation in Spring MVC.
<request-mapping>
元素允许您将多个 Spring Integration HTTP 入站端点配置到同一个 path
(甚至相同的 supported-methods
),并允许您基于传入的 HTTP 请求提供不同的下游消息流。
The <request-mapping>
element lets you configure several Spring Integration HTTP inbound endpoints to the same path
(or even the same supported-methods
) and lets you provide different downstream message flows based on incoming HTTP requests.
或者,你也可以只声明一个 HTTP 入站端点并使用 Spring Integration 流程中的路由和过滤逻辑来实现相同的结果。这让你能尽早地将 Message 放入流程中。以下示例显示了如何执行此操作:
Alternatively, you can also declare only one HTTP inbound endpoint and apply routing and filtering logic within the Spring Integration flow to achieve the same result.
This lets you get the Message
into the flow as early as possibly.
The following example shows how to do so:
<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"/>
有关处理程序映射的更多信息,请参见 the Spring Framework Web Servlet documentation 或 the Spring Framework Web Reactive documentation。
For more information regarding handler mappings, see the Spring Framework Web Servlet documentation or the Spring Framework Web Reactive documentation.
IntegrationRequestMappingHandlerMapping
扩展了 Spring MVC RequestMappingHandlerMapping
类,继承了大部分逻辑,尤其是 handleNoMatch(Set, String, HttpServletRequest)
,当映射由于某一原因不匹配时,它会为 HTTP 响应抛出具体的 4xx
错误,从而阻止调用应用程序上下文中任何剩余的映射处理程序。出于此原因,不支持为 Spring Integration 和 Spring MVC 请求映射(例如,一个 POST
,另一个 GET
)配置相同的路径;MVC 映射将找不到。
The IntegrationRequestMappingHandlerMapping
extends the Spring MVC RequestMappingHandlerMapping
class, inheriting most of its logic, especially handleNoMatch(Set, String, HttpServletRequest)
, which throws a specific 4xx
error for the HTTP response, when mapping doesn’t match for some reason, preventing calls to any remaining mapping handlers in the application context.
For this reason, configuring the same path for both Spring Integration and Spring MVC request mappings (e.g. POST
in one and GET
in the other) is not supported; the MVC mapping will not be found..
Cross-origin Resource Sharing (CORS) Support
从 4.2 版本开始,你可以使用 <cross-origin>
元素配置 <http:inbound-channel-adapter>
和 <http:inbound-gateway>
。它表示与 Spring MVC 的 @CrossOrigin
针对 @Controller
注解相同的选项,并允许为 Spring Integration HTTP 端点配置跨源资源共享 (CORS):
Starting with version 4.2, you can configure the <http:inbound-channel-adapter>
and <http:inbound-gateway>
with a <cross-origin>
element.
It represents the same options as Spring MVC’s @CrossOrigin
for @Controller
annotations and allows the configuration of cross-origin resource sharing (CORS) for Spring Integration HTTP endpoints:
-
origin
: List of allowed origins. Themeans that all origins are allowed. These values are placed in the
Access-Control-Allow-Origin
header of both the pre-flight and actual responses. The default value is.
-
allowed-headers
: Indicates which request headers can be used during the actual request. Themeans that all headers requested by the client are allowed. This property controls the value of the pre-flight response’s
Access-Control-Allow-Headers
header. The default value is.
-
exposed-headers
: List of response headers that the user-agent lets the client access. This property controls the value of the actual response’sAccess-Control-Expose-Headers
header. -
method
: The HTTP request methods to allow:GET
,POST
,HEAD
,OPTIONS
,PUT
,PATCH
,DELETE
,TRACE
. Methods specified here overrides those insupported-methods
. -
allow-credentials
: Set totrue
if the browser should include any cookies associated to the domain of the request orfalse
if it should not. An empty string ("") means undefined. Iftrue
, the pre-flight response includes theAccess-Control-Allow-Credentials=true
header. The default value istrue
. -
max-age
: Controls the cache duration for pre-flight responses. Setting this to a reasonable value can reduce the number of pre-flight request-response interactions required by the browser. This property controls the value of theAccess-Control-Max-Age
header in the pre-flight response. A value of-1
means undefined. The default value is 1800 seconds (30 minutes).
CORS Java 配置由 org.springframework.integration.http.inbound.CrossOrigin
类表示,其实例可以注入到 HttpRequestHandlingEndpointSupport
Bean 中。
The CORS Java Configuration is represented by the org.springframework.integration.http.inbound.CrossOrigin
class, instances of which can be injected into the HttpRequestHandlingEndpointSupport
beans.
Response Status Code
从 4.1 版本开始,你可以使用 status-code-expression
配置 <http:inbound-channel-adapter>
以覆盖默认的 200 OK
状态。表达式必须返回一个可转换为 org.springframework.http.HttpStatus
枚举值的对象。evaluationContext
有一个 BeanResolver
,从 5.1 版本开始,会将 RequestEntity<?>
作为根对象提供。一个示例可能是运行时解析返回状态代码值的某个限定 Bean。然而,它很可能被设置为固定值,例如 status-code=expression="204"
(无内容)或 status-code-expression="T(org.springframework.http.HttpStatus).NO_CONTENT"
。默认情况下,status-code-expression
为 null,这意味着返回正常的“200 OK”响应状态。使用 RequestEntity<?>
作为根对象,状态代码可以有条件,例如请求方法、某个标题、URI 内容甚至请求正文。以下示例显示了如何将状态代码设置为 ACCEPTED
:
Starting with version 4.1, you can configure the <http:inbound-channel-adapter>
with a status-code-expression
to override the default 200 OK
status.
The expression must return an object that can be converted to an org.springframework.http.HttpStatus
enum value.
The evaluationContext
has a BeanResolver
and, starting with version 5.1, is supplied with the RequestEntity<?>
as root object.
An example might be to resolve, at runtime, some scoped bean that returns a status code value.
However, most likely, it is set to a fixed value such as status-code=expression="204"
(No Content), or status-code-expression="T(org.springframework.http.HttpStatus).NO_CONTENT"
.
By default, status-code-expression
is null, meaning that the normal '200 OK' response status is returned.
Using the RequestEntity<?>
as root object, the status code can be conditional e.g. on the request method, some header, URI content or even request body.
The following example shows how to set the status code to 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>
从回复 Message
的 http_statusCode
标题中解析“状态代码”。从 4.2 版本开始,当在 reply-timeout
中未收到回复时的默认响应状态代码是 500 Internal Server Error
。有两种方法可以修改此行为:
The <http:inbound-gateway>
resolves the 'status code' from the http_statusCode
header of the reply Message
.
Starting with version 4.2, the default response status code when no reply is received within the reply-timeout
is 500 Internal Server Error
.
There are two ways to modify this behavior:
-
Add a
reply-timeout-status-code-expression
. This has the same semantics as thestatus-code-expression
on the inbound adapter. -
Add an
error-channel
and return an appropriate message with an HTTP status code header, as the following example shows:[source, xml]
<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
技术时所使用值。
The payload of the ErrorMessage
is a MessageTimeoutException
.
It must be transformed to something that can be converted by the gateway, such as a String
.
A good candidate is the exception’s message property, which is the value used when you use the expression
technique.
如果错误流程在主流程超时后超时,会返回 500 Internal Server Error
,或者,如果存在 reply-timeout-status-code-expression
,则对其进行评估。
If the error flow times out after a main flow timeout, 500 Internal Server Error
is returned, or, if the reply-timeout-status-code-expression
is present, it is evaluated.
以前,超时的默认状态代码为 |
Previously, the default status code for a timeout was |
同样从 5.4 版本开始,在准备请求消息时遇到的错误将被发送到错误通道(如果提供了)。有关抛出适当异常的决定应当通过检查异常来在错误流程中做出。以前,任何异常都会被简单抛出,导致 HTTP 500 服务器错误响应状态,但在某些情况下,问题可能是由不正确的请求参数造成的,所以应该改为抛出一个带有 4xx 客户端错误状态的 ResponseStatusException
。有关详细信息,请参阅 ResponseStatusException
。发送到此错误通道的 ErrorMessage
包含原始异常作为有效负载以进行分析。
Also starting with version 5.4, an error that is encountered while preparing the request message is sent to the error channel (if provided).
A decision about throwing an appropriate exception should be done in the error flow by examining the exception.
Previously, any exceptions were simply thrown, causing an HTTP 500 server error response status, but in some cases the problem can be caused by incorrect request params, so a ResponseStatusException
with a 4xx client error status should be thrown instead.
See ResponseStatusException
for more information.
The ErrorMessage
sent to this error channel contains the original exception as the payload for analysis.
URI Template Variables and Expressions
通过将 path
属性与 payload-expression
属性和 header
元素结合使用,你可以高度灵活地映射入站请求数据。
By using the path
attribute in conjunction with the payload-expression
attribute and the header
element, you have a high degree of flexibility for mapping inbound request data.
在以下示例配置中,入站通道适配器被配置为使用以下 URI 接受请求:
In the following example configuration, an inbound channel adapter is configured to accept requests using the following URI:
/first-name/{firstName}/last-name/{lastName}
当你使用 payload-expression
属性时,{firstName}
URI 模板变量被映射为 Message
有效负载,而 {lastName}
URI 模板变量被映射为 lname
消息标题,如下面示例中定义:
When you use the payload-expression
attribute, the {firstName}
URI template variable maps to be the Message
payload, while the {lastName}
URI template variable maps to the lname
message header, as defined in the following example:
<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 template patterns。
For more information about URI template variables, see uri template patterns in the Spring Reference Manual.
从 Spring Integration 3.0 开始,除了在有效负载和标题表达式中提供现有的 #pathVariables
和 #requestParams
变量外,我们还添加了其他有用的表达式变量:
Since Spring Integration 3.0, in addition to the existing #pathVariables
and #requestParams
variables being available in payload and header expressions, we added other useful expression variables:
-
#requestParams
: TheMultiValueMap
from theServletRequest
parameterMap
. -
#pathVariables
: TheMap
from URI Template placeholders and their values. -
#matrixVariables
: TheMap
ofMultiValueMap
according to the Spring MVC Specification. Note that#matrixVariables
requires Spring MVC 3.2 or higher. -
#requestAttributes
: Theorg.springframework.web.context.request.RequestAttributes
associated with the current request. -
#requestHeaders
: Theorg.springframework.http.HttpHeaders
object from the current request. -
#cookies
: TheMultiValueMap<String, Cookie>
ofjakarta.servlet.http.Cookie
instances from the current request.
请注意,如果消息流程是单线程且存在于请求线程内,所有这些值(以及其他值)都可以通过 ThreadLocal
org.springframework.web.context.request.RequestAttributes
变量在下游消息流程中的表达式中访问。以下示例配置了一个使用 expression
属性的转换器:
Note that all these values (and others) can be accessed within expressions in the downstream message flow through the ThreadLocal
org.springframework.web.context.request.RequestAttributes
variable, if that message flow is single-threaded and lives within the request thread.
The following example configures a transformer that uses an expression
attribute:
<int-:transformer
expression="T(org.springframework.web.context.request.RequestContextHolder).
requestAttributes.request.queryString"/>
Outbound
要配置出站网关,你可以使用命名空间支持。以下代码段显示了出站 HTTP 网关的可用配置选项:
To configure the outbound gateway, you can use the namespace support. The following code snippet shows the available configuration options for an outbound HTTP gateway:
<int-http:outbound-gateway id="example"
request-channel="requests"
url="http://localhost/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-method`为 `POST
,默认响应类型为 null。对于空响应类型,只要 HTTP 状态是成功的(非成功的状态代码会引发异常),响应 Message`的负载就包含 `ResponseEntity
。如果您预计一种不同类型,例如 String
,请将其提供为完全限定的类名(在前一个示例中为 java.lang.String
)。另请参阅 HTTP Outbound Components中有关空响应正文的注释。
Most importantly, notice that the 'http-method' and 'expected-response-type' attributes are provided.
Those are two of the most commonly configured values.
The default http-method
is POST
, and the default response type is null.
With a null response type, the payload of the reply Message
contains the ResponseEntity
, as long as its HTTP status is a success (non-successful status codes throw exceptions).
If you expect a different type, such as a String
, provide that as a fully-qualified class name (java.lang.String
in the preceding example).
See also the note about empty response bodies in HTTP Outbound Components.
从 Spring Integration 2.1 开始,HTTP 出站网关的 request-timeout
属性已重命名为 reply-timeout
,以更好地反映其意图。
Beginning with Spring Integration 2.1, the request-timeout
attribute of the HTTP outbound gateway was renamed to reply-timeout
to better reflect its intent.
从 Spring Integration 2.2 开始,默认不再支持 HTTP 上的 Java 序列化。以前,当将 expected-response-type
属性设置为 Serializable
对象时,Accept
标题未正确设置。从 Spring Integration 2.2 开始,SerializingHttpMessageConverter
已更新为将 Accept
标题设置为 application/x-java-serialized-object
。
Since Spring Integration 2.2, Java serialization over HTTP is no longer enabled by default.
Previously, when setting the expected-response-type
attribute to a Serializable
object, the Accept
header was not properly set up.
Since Spring Integration 2.2, the SerializingHttpMessageConverter
has now been updated to set the Accept
header to application/x-java-serialized-object
.
但是,由于这可能导致与现有应用程序不兼容,因此决定不再自动将此转换器添加到 HTTP 端点。如果您希望使用 Java 序列化,您可以使用 message-converters
属性(使用 XML 配置时)或使用 setMessageConverters()
方法(使用 Java 配置时)将 SerializingHttpMessageConverter
添加到合适的端点。或者,您可能希望考虑改用 JSON,通过在类路径上具有 the Jackson library 即可启用。
However, because this could cause incompatibility with existing applications, it was decided to no longer automatically add this converter to the HTTP endpoints.
If you wish to use Java serialization, you can add the SerializingHttpMessageConverter
to the appropriate endpoints, by using the message-converters
attribute (when you use XML configuration) or by using the setMessageConverters()
method (in Java configuration).
Alternatively, you may wish to consider using JSON instead, which is enabled by having the Jackson library on the classpath.
从 Spring Integration 2.2 开始,你还可以使用 SpEL 和 http-method-expression
属性动态确定 HTTP 方法。请注意,此属性与 http-method
互斥。你还可以使用 expected-response-type-expression
属性代替 expected-response-type
并提供任何有效的 SpEL 表达式以确定响应的类型。以下配置示例使用 expected-response-type-expression
:
Beginning with Spring Integration 2.2, you can also determine the HTTP method dynamically by using SpEL and the http-method-expression
attribute.
Note that this attribute is mutually exclusive with http-method
.
You can also use the expected-response-type-expression
attribute instead of expected-response-type
and provide any valid SpEL expression that determines the type of the response.
The following configuration example uses expected-response-type-expression
:
<int-http:outbound-gateway id="example"
request-channel="requests"
url="http://localhost/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
。这意味着成功的响应会在不向回复信道发送任何消息的情况下执行。在任何非成功响应状态码的情况下,它都会抛出异常。配置看起来与网关非常相似,如下例所示:
If your outbound adapter is to be used in a unidirectional way, you can use an outbound-channel-adapter
instead.
This means that a successful response executes without sending any messages to a reply channel.
In the case of any non-successful response status code, it throws an exception.
The configuration looks very similar to the gateway, as the following example shows:
<int-http:outbound-channel-adapter id="example"
url="http://localhost/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 表达式,以 To specify the URL, you can use either the 'url' attribute or the 'url-expression' attribute.
The 'url' attribute takes a simple string (with placeholders for URI variables, as described below).
The 'url-expression' is a SpEL expression, with the 在之前的版本中,一些用户使用占位符用 URI 变量替换整个 URL。Spring 3.1 中的更改可能会导致转义字符(例如“?”)出现一些问题。因此,我们建议您使用“url-expression”属性来生成 URL 中的全部运行时要素。 In previous releases, some users used the place holders to replace the entire URL with a URI variable. Changes in Spring 3.1 can cause some issues with escaped characters, such as '?'. For this reason, we recommend that, if you wish to generate the URL entirely at runtime, you use the 'url-expression' attribute. |
Mapping URI Variables
如果您的 URL 包含 URI 变量,则可以通过使用 uri-variable
元素映射这些变量。此元素可供 HTTP 出站网关和 HTTP 出站通道适配器使用。以下示例将 zipCode
URI 变量映射到一个表达式:
If your URL contains URI variables, you can map them by using the uri-variable
element.
This element is available for the HTTP outbound gateway and the HTTP outbound channel adapter.
The following example maps the zipCode
URI variable to an expression:
<int-http:outbound-gateway id="trafficGateway"
url="https://local.yahooapis.com/trafficData?appid=YdnDemo&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
元素定义两个属性:“name”和“expression”。“name”属性标识 URI 变量的名称,而“expression”属性用于设置实际值。通过使用“expression”属性,您可以充分利用 Spring 表达式语言 (SpEL) 的强大功能,该功能可以让您全面动态访问邮件正文和邮件头。例如,在前面的配置中,在 Message
的正文对象上调用 getZip()
方法,并将该方法的结果用作名为“zipCode”的 URI 变量的值。
The uri-variable
element defines two attributes: name
and expression
.
The name
attribute identifies the name of the URI variable, while the expression
attribute is used to set the actual value.
By using the expression
attribute, you can leverage the full power of the Spring Expression Language (SpEL), which gives you full dynamic access to the message payload and the message headers.
For example, in the preceding configuration, the getZip()
method is invoked on the payload object of the Message
and the result of that method is used as the value of the URI variable named 'zipCode'.
自 Spring Integration 3.0 起,HTTP 出站端点支持 uri-variables-expression
属性,用于指定应计算的“expression”,得到 URL 模板中所有 URI 变量占位符的 Map
。它提供了一种机制,通过该机制您可以根据出站邮件使用不同的变量表达式。此属性与 <uri-variable/>
元素互斥。以下示例说明了如何使用 uri-variables-expression
属性:
Since Spring Integration 3.0, HTTP outbound endpoints support the uri-variables-expression
attribute to specify an expression
that should be evaluated, resulting in a Map
of all URI variable placeholders within the URL template.
It provides a mechanism whereby you can use different variable expressions, based on the outbound message.
This attribute is mutually exclusive with the <uri-variable/>
element.
The following example shows how to use the uri-variables-expression
attribute:
<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
的定义如下:
uriVariablesBean
might be defined as follows:
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;
}
}
|
The |
重要信息:uriVariablesExpression
属性提供了一个非常强大的机制,用于计算 URI 变量。我们预计人们大多使用简单的表达式,例如前面的示例。但是,您还可以配置一些内容,例如 "@uriVariablesBean.populate(#root)",将返回的 map 中的一个表达式设为 `variables.put("thing1", EXPRESSION_PARSER.parseExpression(message.getHeaders().get("thing2", String.class)));
,其中的表达式通过名为 thing2
的邮件头动态提供。由于该邮件头可能来自不受信任的来源,因此 HTTP 出站端点在计算这些表达式时使用 SimpleEvaluationContext
。SimpleEvaluationContext
仅使用 SpEL 功能的一部分。如果您信任邮件来源并希望使用受限的 SpEL 结构,则将出站端点的 trustedSpel
属性设置为 “true”。
IMPORTANT
The uriVariablesExpression
property provides a very powerful mechanism for evaluating URI variables.
We anticipate that people mostly use simple expressions, such as the preceding example.
However, you can also configure something such as "@uriVariablesBean.populate(#root)"
with an expression in the returned map being variables.put("thing1", EXPRESSION_PARSER.parseExpression(message.getHeaders().get("thing2", String.class)));
, where the expression is dynamically provided in the message header named thing2
.
Since the header may come from an untrusted source, the HTTP outbound endpoints use SimpleEvaluationContext
when evaluating these expressions.
The SimpleEvaluationContext
uses only a subset of SpEL features.
If you trust your message sources and wish to use the restricted SpEL constructs, set the trustedSpel
property of the outbound endpoint to true
.
您可以通过使用自定义 url-expression
和一些用于构建和编码 URL 参数的实用程序,实现需要针对每封邮件提供一组动态 URI 变量的场景。以下示例演示了如何执行此操作:
You can achieve scenarios that need to supply a dynamic set of URI variables on a per-message basis by using a custom url-expression
and some utilities for building and encoding URL parameters.
The following example shows how to do so:
url-expression="T(org.springframework.web.util.UriComponentsBuilder)
.fromHttpUrl('https://HOST:PORT/PATH')
.queryParams(payload)
.build()
.toUri()"
queryParams()
方法需要一个 MultiValueMap<String, String>
作为参数,因此您可以在执行请求之前预先构建一组真正的 URL 查询参数。
The queryParams()
method expects a MultiValueMap<String, String>
as an argument, so you can build a real set of URL query parameters in advance, before performing the request.
整个 queryString
还可以表示为一个 uri-variable
,如下例所示:
The whole queryString
can also be presented as a uri-variable
, as the following example shows:
<int-http:outbound-gateway id="proxyGateway" request-channel="testChannel"
url="http://testServer/test?{queryString}">
<int-http:uri-variable name="queryString" expression="'a=A&b=B'"/>
</int-http:outbound-gateway>
在这种情况下,您必须手动提供 URL 编码。例如,您可以为此目的使用 org.apache.http.client.utils.URLEncodedUtils#format()
。如前所述,可以通过使用以下 Java Streams 片段将手动构建的 MultiValueMap<String, String>
转换为 List<NameValuePair>
format()
方法参数:
In this case, you must manually provide the URL encoding.
For example, you can use the org.apache.http.client.utils.URLEncodedUtils#format()
for this purpose.
As mentioned earlier, a manually built MultiValueMap<String, String>
can be converted to the List<NameValuePair>
format()
method argument by using the following Java Streams snippet:
List<NameValuePair> nameValuePairs =
params.entrySet()
.stream()
.flatMap(e -> e
.getValue()
.stream()
.map(v -> new BasicNameValuePair(e.getKey(), v)))
.collect(Collectors.toList());
Controlling URI Encoding
默认情况下,在发送请求之前,会将 URL 字符串编码(请参见 link:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html[UriComponentsBuilder
)到 URI 对象。在某些具有非标准 URI(例如 RabbitMQ REST API)的场景中,不希望执行编码。<http:outbound-gateway/>
和 <http:outbound-channel-adapter/>
提供 encoding-mode
属性。要禁用对 URL 的编码,请将此属性设置为 NONE
(默认情况下,它为 TEMPLATE_AND_VALUES
)。如果您希望部分编码 URL 的某些部分,请在 <uri-variable/>
中使用 expression
,如下例所示:
By default, the URL string is encoded (see UriComponentsBuilder
) to the URI object before sending the request.
In some scenarios with a non-standard URI (such as the RabbitMQ REST API), it is undesirable to perform the encoding.
The <http:outbound-gateway/>
and <http:outbound-channel-adapter/>
provide an encoding-mode
attribute.
To disable encoding the URL, set this attribute to NONE
(by default, it is TEMPLATE_AND_VALUES
).
If you wish to partially encode some part of the URL, use an expression
within a <uri-variable/>
, as the following example shows:
<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 module和 Web Services module中类似的出站组件中应用相同的配置。对于非常复杂的场景,建议在外部提供的 `RestTemplate`上配置一个 `UriTemplateHandler
;或者在 WebFlux 的情况下 - 在其 WebClient`上进行配置 `UriBuilderFactory
。
With Java DSL this option can be controlled by the BaseHttpMessageHandlerSpec.encodingMode()
option.
The same configuration applies for similar outbound components in the WebFlux module and Web Services module.
For much sophisticated scenarios it is recommended to configure an UriTemplateHandler
on the externally provided RestTemplate
; or in case of WebFlux - WebClient
with it UriBuilderFactory
.