HTTP 名前空間のサポート
Spring Integration は、http
名前空間と対応するスキーマ定義を提供します。構成に含めるには、アプリケーションコンテキスト構成ファイルで次の名前空間宣言を指定します。
<?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 受信リクエストを処理するための 2 つのコンポーネント、inbound-channel-adapter
および inbound-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 (Javadoc) を導入することで REST サポートを改善しました。この実装は、Spring Framework 3.1 以降で提供される拡張 REST サポートに依存しています。 |
HTTP 受信・ゲートウェイまたは HTTP 受信・チャネルアダプターの構文解析により、型 IntegrationRequestMappingHandlerMapping
(Javadoc) の integrationRequestMappingHandlerMapping
Bean が登録されます (まだ登録されていない場合)。HandlerMapping
(Javadoc) のこの特定の実装は、そのロジックを RequestMappingInfoHandlerMapping
(Javadoc) に委譲します。この実装は、Spring MVC の org.springframework.web.bind.annotation.RequestMapping
(Javadoc) アノテーションと同様の機能を提供します。
詳しくは、@RequestMapping を使用したリクエストのマッピングを参照してください。 |
この目的のために、Spring Integration 3.0 は <request-mapping>
要素を導入します。このオプションの要素を <http:inbound-channel-adapter>
および <http:inbound-gateway>
に追加できます。path
および supported-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
(Javadoc) のインスタンスを関連付けます。この RequestMapping
インスタンスは、次に Spring MVC RequestMappingInfo
(Javadoc) に変換されます。
<request-mapping>
要素は、次の属性を提供します。
headers
params
consumes
produces
<http:inbound-channel-adapter>
または <http:inbound-gateway>
の path
および supported-methods
属性を使用すると、<request-mapping>
属性は、Spring MVC の org.springframework.web.bind.annotation.RequestMapping
アノテーションによって提供されるそれぞれのオプションに直接変換されます。
<request-mapping>
要素を使用すると、複数の Spring Integration HTTP 受信エンドポイントを同じ path
(または同じ supported-methods
)に構成でき、受信 HTTP リクエストに基づいて異なるダウンストリームメッセージフローを提供できます。
または、1 つの 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 サーブレットドキュメントまたは Spring Framework Web リアクティブドキュメントを参照してください。
IntegrationRequestMappingHandlerMapping は Spring MVC RequestMappingHandlerMapping クラスを継承し、そのロジックのほとんど、特に handleNoMatch(Set, String, HttpServletRequest) を継承し、何らかの理由でマッピングが一致しない場合に HTTP レスポンスに対して特定の 4xx エラーをスローし、アプリケーションコンテキスト内の残りのマッピングハンドラーの呼び出しを防ぎます。このため、Spring Integration と Spring MVC の両方のリクエストマッピング (たとえば、一方の POST と他方の GET ) に同じパスを設定することはサポートされていません。MVC マッピングが見つかりません .. |
クロスオリジンリソースシェアリング(CORS)サポート
バージョン 4.2 以降、<http:inbound-channel-adapter>
および <http:inbound-gateway>
を <cross-origin>
エレメントで構成できます。これは、Spring MVC の @Controller
アノテーションの @CrossOrigin
と同じオプションを表し、Spring Integration HTTP エンドポイントのクロスオリジンリソースシェアリング (CORS) の設定を可能にします。
origin
: 許可された起源のリスト。*
は、すべての発信元が許可されることを意味します。これらの値は、プリフライトレスポンスと実際のレスポンスの両方のAccess-Control-Allow-Origin
ヘッダーに配置されます。デフォルト値は*
です。allowed-headers
: 実際のリクエスト中に使用できるリクエストヘッダーを示します。*
は、クライアントによってリクエストされたすべてのヘッダーが許可されることを意味します。このプロパティは、プリフライトレスポンスのAccess-Control-Allow-Headers
ヘッダーの値を制御します。デフォルト値は*
です。exposed-headers
: ユーザーエージェントがクライアントにアクセスを許可するレスポンスヘッダーのリスト。このプロパティは、実際のレスポンスのAccess-Control-Expose-Headers
ヘッダーの値を制御します。method
: 許可する HTTP リクエストメソッド:GET
、POST
、HEAD
、OPTIONS
、PUT
、PATCH
、DELETE
、TRACE
ここで指定されたメソッドは、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 を解決することができます。ただし、status-code=expression="204"
(コンテンツなし) や status-code-expression="T(org.springframework.http.HttpStatus).NO_CONTENT"
などの固定値に設定されている場合がほとんどです。デフォルトでは、status-code-expression
は null であり、通常の "200OK " レスポンス状況が戻されることを意味します。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>
は、レスポンス Message
の http_statusCode
ヘッダーから「ステータスコード」を解決します。バージョン 4.2 以降、reply-timeout
内でレスポンスが受信されない場合のデフォルトのレスポンスステータスコードは 500 Internal Server Error
です。この動作を変更するには 2 つの方法があります。
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
など、ゲートウェイで変換できるものに変換する必要があります。適切な候補は、例外のメッセージプロパティです。これは、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
parameterMap
からのMultiValueMap
。#pathVariables
: URI テンプレートプレースホルダーからのMap
とその値。#matrixVariables
: Spring MVC 仕様に準じたMultiValueMap
のMap
。#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="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" 属性が提供されていることに注意してください。これらは、最も一般的に設定される 2 つの値です。デフォルトの http-method
は POST
であり、デフォルトのレスポンス型は 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 シリアライゼーションはデフォルトで有効ではなくなりました。以前は、 ただし、これにより既存のアプリケーションとの非互換性が発生する可能性があるため、このコンバーターを HTTP エンドポイントに自動的に追加しないことにしました。Java 直列化を使用する場合は、 |
Spring Integration 2.2 以降、SpEL と http-method-expression
属性を使用して HTTP メソッドを動的に決定することもできます。この属性は http-method
と相互に排他的であることに注意してください。expected-response-type
の代わりに expected-response-type-expression
属性を使用して、レスポンスの型を決定する有効な SpEL 式を提供することもできます。次の構成例では 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
を使用できます。これは、レスポンスチャネルにメッセージを送信せずに正常なレスポンスが実行されることを意味します。レスポンスステータスコードが失敗した場合、例外をスローします。次の例に示すように、構成はゲートウェイに非常に似ています。
<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" は、 以前のリリースでは、一部のユーザーはプレースホルダーを使用して、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&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
の 2 つの属性を定義します。name
属性は URI 変数の名前を識別し、expression
属性は実際の値を設定するために使用されます。expression
属性を使用すると、メッセージペイロードとメッセージヘッダーへの完全な動的アクセスを提供する Spring 式言語 (SpEL) の機能をフルに活用できます。例: 上記の構成では、Message
のペイロードオブジェクトで getZip()
メソッドが呼び出され、そのメソッドの結果が 'zipCode' という名前の URI 変数の値として使用されます。
Spring Integration 3.0 以降、HTTP 送信エンドポイントは、評価する必要がある expression
を指定する uri-variables-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 は Map に評価される必要があります。Map の値は、String または Expression のインスタンスでなければなりません。この Map は、送信 Message のコンテキストでそれらの式を使用することにより、URI 変数プレースホルダーのさらなる解決のために ExpressionEvalMap に提供されます。 |
重要 uriVariablesExpression
プロパティは、URI 変数を評価するための非常に強力なメカニズムを提供します。前述の例のような単純な表現を使用することが多いと予想されます。ただし、返されたマップ内の式が variables.put("thing1", EXPRESSION_PARSER.parseExpression(message.getHeaders().get("thing2", String.class)));
である "@uriVariablesBean.populate(#root)"
などを構成することもできます。この場合、式は thing2
という名前のメッセージヘッダーに動的に提供されます。ヘッダーは信頼できないソースからのものである可能性があるため、HTTP 送信 エンドポイントはこれらの式を評価するときに SimpleEvaluationContext
を使用します。SimpleEvaluationContext
は SpEL 機能のサブセットのみを使用します。メッセージソースを信頼し、制限された SpEL 構造を使用したい場合は、送信エンドポイントの trustedSpel
プロパティを true
に設定します。
URL パラメーターを作成およびエンコードするためのカスタム url-expression
およびいくつかのユーティリティを使用することにより、メッセージごとに 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&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 文字列は、リクエストを送信する前に URI オブジェクトにエンコードされます ( UriComponentsBuilder
(Javadoc) を参照)。非標準の 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 サービスモジュールの同様の送信コンポーネントに適用されます。より高度なシナリオでは、外部で提供される RestTemplate
で UriTemplateHandler
を構成することをお勧めします。または WebFlux- WebClient
の場合は UriBuilderFactory
です。