HTTP サポート
Spring Integration の HTTP サポートにより、HTTP リクエストの実行と受信 HTTP リクエストの処理が可能になります。HTTP サポートは、次のゲートウェイ実装で構成されています: HttpInboundEndpoint
および HttpRequestExecutingMessageHandler
。WebFlux サポートも参照してください。
この依存関係をプロジェクトに含める必要があります。
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-http</artifactId>
<version>5.5.8</version>
</dependency>
compile "org.springframework.integration:spring-integration-http:5.5.8"
javax.servlet:javax.servlet-api
依存関係は、ターゲットサーブレットコンテナーで提供する必要があります。
HTTP 受信コンポーネント
HTTP 経由でメッセージを受信するには、HTTP 受信チャネルアダプターまたは HTTP 受信ゲートウェイを使用する必要があります。HTTP 受信アダプターをサポートするには、Apache Tomcat (英語) や Jetty (英語) などのサーブレットコンテナー内にデプロイする必要があります。これを行う最も簡単な方法は、web.xml
ファイルで次のサーブレット定義を提供することにより、Spring の HttpRequestHandlerServlet
(Javadoc) を使用することです。
<servlet>
<servlet-name>inboundGateway</servlet-name>
<servlet-class>o.s.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
サーブレット名が Bean 名と一致することに注意してください。HttpRequestHandlerServlet
の使用の詳細については、Spring Framework リファレンスドキュメントの一部である Spring を使用したリモートおよび Web サービスを参照してください。
Spring MVC アプリケーション内で実行している場合、前述の明示的なサーブレット定義は必要ありません。その場合、Spring MVC コントローラー Bean の場合と同様に、ゲートウェイの Bean 名を URL パスと照合できます。詳細については、Spring Framework リファレンスドキュメントの一部である Web MVC フレームワークを参照してください。
サンプルアプリケーションと対応する構成については、Spring Integration サンプル [GitHub] (英語) リポジトリを参照してください。Spring Integration の HTTP サポートを示す HTTP サンプル [GitHub] (英語) アプリケーションが含まれています。 |
次の例 Bean は、HTTP 受信エンドポイントを定義します。
<bean id="httpInbound"
class="org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway">
<property name="requestChannel" ref="httpRequestChannel" />
<property name="replyChannel" ref="httpReplyChannel" />
</bean>
HttpRequestHandlingMessagingGateway
は HttpMessageConverter
インスタンスのリストを受け入れるか、デフォルトリストに依存します。コンバーターを使用すると、HttpServletRequest
から Message
へのマッピングをカスタマイズできます。デフォルトのコンバーターは、コンテンツ型が text
で始まる POST
リクエストに対して String
メッセージを作成する単純な戦略をカプセル化します。詳細については、Javadoc を参照してください。追加のフラグ(mergeWithDefaultConverters
)をカスタム HttpMessageConverter
のリストとともに設定して、カスタムコンバーターの後にデフォルトコンバーターを追加できます。デフォルトでは、このフラグは false
に設定されています。これは、カスタムコンバーターがデフォルトリストを置き換えることを意味します。
メッセージ変換プロセスは、(オプションの) requestPayloadType
プロパティと受信 Content-Type
ヘッダーを使用します。バージョン 4.3 以降、リクエストにコンテンツ型ヘッダーがない場合、RFC 2616
で推奨されているように、application/octet-stream
が想定されます。以前は、このようなメッセージの本文は無視されていました。
Spring Integration 2.0 はマルチパートファイルのサポートを実装しました。リクエストが MultipartHttpServletRequest
としてラップされている場合、デフォルトのコンバーターを使用すると、そのリクエストは、個々のパートのコンテンツ型に応じて、バイト配列、文字列、Spring の MultipartFile
のインスタンスである値を含む MultiValueMap
である Message
ペイロードに変換されます。
HTTP 受信エンドポイントは、Bean の名前が multipartResolver (Spring の DispatcherServlet が期待する名前)の場合、コンテキスト内で MultipartResolver を見つけます。その Bean が見つかると、受信リクエストマッパーでマルチパートファイルのサポートが有効になります。そうでない場合、マルチパートファイルリクエストを Spring Integration Message にマップしようとすると失敗します。MultipartResolver に対する Spring のサポートの詳細については、Spring リファレンスマニュアルを参照してください。 |
|
クライアントにレスポンスを送信する場合、ゲートウェイの動作をカスタマイズする方法はいくつかあります。デフォルトでは、ゲートウェイは 200
ステータスコードを返送することにより、リクエストが受信されたことを確認します。Spring MVC ViewResolver
によって解決される "viewName" を提供することにより、このレスポンスをカスタマイズすることができます。ゲートウェイが Message
へのレスポンスを期待する必要がある場合は、expectReply
フラグ (コンストラクター引数) を設定して、HTTP レスポンスを作成する前にゲートウェイが Message
のレスポンスを待機するようにすることができます。次の例では、ビュー名を持つ Spring MVC コントローラーとして機能するようにゲートウェイを構成しています。
<bean id="httpInbound"
class="org.springframework.integration.http.inbound.HttpRequestHandlingController">
<constructor-arg value="true" /> <!-- indicates that a reply is expected -->
<property name="requestChannel" ref="httpRequestChannel" />
<property name="replyChannel" ref="httpReplyChannel" />
<property name="viewName" value="jsonView" />
<property name="supportedMethodNames" >
<list>
<value>GET</value>
<value>DELETE</value>
</list>
</property>
</bean>
true
の constructor-arg
値のため、応答を待機します。上記の例は、ゲートウェイで受け入れられる HTTP メソッド(デフォルトでは POST
および GET
)をカスタマイズする方法も示しています。
応答メッセージはモデルマップで利用できます。デフォルトでは、そのマップエントリのキーは "reply" ですが、エンドポイントの構成で "replyKey" プロパティを設定することにより、このデフォルトをオーバーライドできます。
ペイロード検証
バージョン 5.2 以降、HTTP 受信エンドポイントに Validator
を提供して、チャネルに送信する前にペイロードをチェックできます。このペイロードは、貴重なデータに関して検証範囲を狭めるために payloadExpression
後に変換および抽出された結果です。検証失敗の処理は、Spring MVC エラー処理にあるものと完全に同じです。
HTTP 送信コンポーネント
このセクションでは、Spring Integration の HTTP 送信コンポーネントについて説明します。
HttpRequestExecutingMessageHandler
を使用する
HttpRequestExecutingMessageHandler
を構成するには、次のような Bean 定義を作成します。
<bean id="httpOutbound"
class="org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler">
<constructor-arg value="http://localhost:8080/example" />
<property name="outputChannel" ref="responseChannel" />
</bean>
この Bean 定義は、RestTemplate
に委譲することにより HTTP リクエストを実行します。次に、そのテンプレートは、HttpMessageConverter
インスタンスのリストに委譲して、Message
ペイロードから HTTP リクエスト本文を生成します。次の例に示すように、これらのコンバーターと ClientHttpRequestFactory
インスタンスを使用するように構成できます。
<bean id="httpOutbound"
class="org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler">
<constructor-arg value="http://localhost:8080/example" />
<property name="outputChannel" ref="responseChannel" />
<property name="messageConverters" ref="messageConverterList" />
<property name="requestFactory" ref="customRequestFactory" />
</bean>
デフォルトでは、HTTP リクエストは、JDK HttpURLConnection
を使用する SimpleClientHttpRequestFactory
のインスタンスを使用して生成されます。Apache Commons HTTP クライアントの使用も、(前述のように) 挿入できる CommonsClientHttpRequestFactory
を通じてサポートされています。
送信ゲートウェイの場合、ゲートウェイによって生成される応答メッセージには、リクエストメッセージに存在するすべてのメッセージヘッダーが含まれます。 |
クッキーを使用する
基本的な Cookie サポートは、送信ゲートウェイの transfer-cookies
属性によって提供されます。true
に設定すると(デフォルトは false
)、レスポンスでサーバーから受信した Set-Cookie
ヘッダーは、レスポンスメッセージで Cookie
に変換されます。このヘッダーは、その後の送信で使用されます。これにより、次のような単純なステートフルな対話が可能になります。
…→logonGateway→…→doWorkGateway→…→logoffGateway→…
transfer-cookies
が false
の場合、受信した Set-Cookie
ヘッダーは応答メッセージ内で Set-Cookie
のままであり、後続の送信でドロップされます。
空のレスポンスボディ HTTP はリクエスト / レスポンスプロトコルです。ただし、レスポンスには本文がなく、ヘッダーのみが含まれる場合があります。この場合、 |
expected-response-type 空のレスポンス本文に関する前述の注意に加えて、レスポンスに本文が含まれている場合、適切な |
バージョン 5.5 以降、HttpRequestExecutingMessageHandler
は extractResponseBody
フラグ(デフォルトでは true
)を公開して、レスポンス本文のみを返すか、提供された expectedResponseType
とは関係なく、ResponseEntity
全体をレスポンスメッセージペイロードとして返します。ボディが ResponseEntity
に存在しない場合、このフラグは無視され、ResponseEntity
全体が返されます。
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
: 現在のリクエストからのjavax.servlet.http.Cookie
インスタンスのMap<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
要素は、2 つの属性 name
および expression
を定義します。name
属性は URI 変数の名前を識別し、expression
属性は実際の値を設定するために使用されます。expression
属性を使用することにより、Spring Expression Language(SpEL)の全機能を活用できます。これにより、メッセージペイロードとメッセージヘッダーへの完全な動的アクセスが可能になります。例: 上記の構成では、getZip()
メソッドが Message
のペイロードオブジェクトで呼び出され、そのメソッドの結果が "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 に提供されます。 |
IMPORTANT
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
です。
Java を使用した HTTP エンドポイントの構成
次の例は、Java で受信ゲートウェイを構成する方法を示しています。
@Bean
public HttpRequestHandlingMessagingGateway inbound() {
HttpRequestHandlingMessagingGateway gateway =
new HttpRequestHandlingMessagingGateway(true);
gateway.setRequestMapping(mapping());
gateway.setRequestPayloadType(String.class);
gateway.setRequestChannelName("httpRequest");
return gateway;
}
@Bean
public RequestMapping mapping() {
RequestMapping requestMapping = new RequestMapping();
requestMapping.setPathPatterns("/foo");
requestMapping.setMethods(HttpMethod.POST);
return requestMapping;
}
次の例は、Java DSL で受信ゲートウェイを構成する方法を示しています。
@Bean
public IntegrationFlow inbound() {
return IntegrationFlows.from(Http.inboundGateway("/foo")
.requestMapping(m -> m.methods(HttpMethod.POST))
.requestPayloadType(String.class))
.channel("httpRequest")
.get();
}
次の例は、Java で送信ゲートウェイを構成する方法を示しています。
@ServiceActivator(inputChannel = "httpOutRequest")
@Bean
public HttpRequestExecutingMessageHandler outbound() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler("http://localhost:8080/foo");
handler.setHttpMethod(HttpMethod.POST);
handler.setExpectedResponseType(String.class);
return handler;
}
次の例は、Java DSL を使用して送信ゲートウェイを構成する方法を示しています。
@Bean
public IntegrationFlow outbound() {
return IntegrationFlows.from("httpOutRequest")
.handle(Http.outboundGateway("http://localhost:8080/foo")
.httpMethod(HttpMethod.POST)
.expectedResponseType(String.class))
.get();
}
タイムアウト処理
HTTP コンポーネントのコンテキストでは、考慮する必要がある 2 つのタイミング領域があります。
Spring Integration チャネルと対話するときのタイムアウト
リモート HTTP サーバーと対話するときのタイムアウト
コンポーネントは、タイムアウトを指定できるメッセージチャネルと対話します。例: HTTP 受信ゲートウェイは、接続された HTTP クライアントから受信したメッセージを(リクエストタイムアウトを使用する)メッセージチャネルに転送し、その結果、HTTP 受信ゲートウェイは、生成に使用されるリプライチャネル(リプライタイムアウトを使用する)からリプライメッセージを受信します。HTTP レスポンス。次の図に視覚的な説明を示します。
送信エンドポイントの場合、リモートサーバーとの対話中にタイミングがどのように機能するかを考慮する必要があります。次の図は、このシナリオを示しています。
HTTP 送信ゲートウェイまたは HTTP 送信チャネルアダプターを使用してアクティブな HTTP リクエストを行う場合、HTTP 関連のタイムアウト動作を構成することができます。これらのインスタンスでは、これら 2 つのコンポーネントは Spring の RestTemplate
(Javadoc) サポートを使用して HTTP リクエストを実行します。
HTTP 送信ゲートウェイと HTTP 送信チャネルアダプターのタイムアウトを構成するには、RestTemplate
Bean を直接参照するか(rest-template
属性を使用)、ClientHttpRequestFactory
(Javadoc) Bean への参照を提供できます(request-factory
属性を使用)。Spring は、ClientHttpRequestFactory
インターフェースの以下の実装を提供します。
SimpleClientHttpRequestFactory
(Javadoc) : HTTP リクエストを作成するために標準の J2SE 機能を使用しますHttpComponentsClientHttpRequestFactory
(Javadoc) : Apache HttpComponents HttpClient (英語) を使用 (Spring 3.1 以降)
request-factory
属性または rest-template
属性を明示的に構成しない場合、デフォルトの RestTemplate
(SimpleClientHttpRequestFactory
を使用)がインスタンス化されます。
一部の JVM 実装では、 例: このメソッドの一部の非標準実装は、指定されたタイムアウトを無視する場合があります。接続タイムアウトの設定を確認するには、getConnectTimeout() を呼び出してください。 特定のニーズがある場合は、タイムアウトをテストする必要があります。 |
Apache HttpComponents HttpClient をプーリング接続マネージャーとともに使用する場合、デフォルトでは、接続マネージャーが特定のルートごとに作成する同時接続は 2 つまで、合計で 20 までしか接続できないことに注意してください。多くの実際のアプリケーションでは、これらの制限は厳しすぎる可能性があります。この重要なコンポーネントの構成については、Apache ドキュメント (英語) を参照してください。 |
次の例では、接続タイムアウトと読み取りタイムアウトをそれぞれ 5 秒に設定した SimpleClientHttpRequestFactory
を使用して、HTTP 送信ゲートウェイを設定します。
<int-http:outbound-gateway url="https://samples.openweathermap.org/data/2.5/weather?q={city}"
http-method="GET"
expected-response-type="java.lang.String"
request-factory="requestFactory"
request-channel="requestChannel"
reply-channel="replyChannel">
<int-http:uri-variable name="city" expression="payload"/>
</int-http:outbound-gateway>
<bean id="requestFactory"
class="org.springframework.http.client.SimpleClientHttpRequestFactory">
<property name="connectTimeout" value="5000"/>
<property name="readTimeout" value="5000"/>
</bean>
HTTP 送信ゲートウェイ
HTTP 送信 ゲートウェイの場合、XML スキーマは Reply-timeout のみを定義します。応答タイムアウトは、 org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler クラスの sendTimeout プロパティにマップされます。より正確には、プロパティは拡張 AbstractReplyProducingMessageHandler
クラスに設定され、最終的には MessagingTemplate
にプロパティが設定されます。
sendTimeout プロパティの値はデフォルトで "-1" になり、接続された MessageChannel
に適用されます。つまり、実装によっては、メッセージチャネルの送信メソッドが無期限にブロックされる場合があります。さらに、sendTimeout プロパティは、実際の MessageChannel 実装にブロッキング送信(「フル」バウンド QueueChannel など)がある場合にのみ使用されます。
HTTP 受信ゲートウェイ
HTTP 受信ゲートウェイの場合、XML スキーマは request-timeout
属性を定義します。これは、HttpRequestHandlingMessagingGateway
クラス(拡張 MessagingGatewaySupport
クラス)で requestTimeout
プロパティを設定するために使用されます。reply-timeout
属性を使用して、同じクラスの replyTimeout
プロパティにマップすることもできます。
両方のタイムアウトプロパティのデフォルトは 1000ms
(1000 ミリ秒または 1 秒)です。最終的に、request-timeout
プロパティは、MessagingTemplate
インスタンスで sendTimeout
を設定するために使用されます。一方、replyTimeout
プロパティは、MessagingTemplate
インスタンスで receiveTimeout
プロパティを設定するために使用されます。
接続タイムアウトをシミュレートするには、10.255.255.10 などのルーティング不可能な IP アドレスに接続できます。 |
HTTP プロキシ構成
プロキシの背後にいて、HTTP 送信アダプターまたはゲートウェイのプロキシ設定を構成する必要がある場合、2 つのアプローチのいずれかを適用できます。ほとんどの場合、プロキシ設定を制御する標準の Java システムプロパティに依存できます。それ以外の場合は、HTTP クライアントリクエストファクトリインスタンスの Spring Bean を明示的に構成できます。
標準 Java プロキシ構成
3 つのシステムプロパティを設定して、HTTP プロトコルハンドラーで使用されるプロキシ設定を構成できます。
http.proxyHost
: プロキシサーバーのホスト名。http.proxyPort
: ポート番号(デフォルトは80
です)。http.nonProxyHosts
: プロキシをバイパスして、直接到達する必要があるホストのリスト。これは、|
で区切られたパターンのリストです。パターンは、ワイルドカードの場合、*
で開始または終了する場合があります。これらのパターンのいずれかに一致するホストには、プロキシ経由ではなく直接接続経由で到達します。
HTTPS の場合、次のプロパティを使用できます。
https.proxyHost
: プロキシサーバーのホスト名。https.proxyPort
: ポート番号。デフォルト値は 80 です。
詳細については、https://docs.oracle.com/javase/jp/8/docs/technotes/guides/net/proxies.html を参照してください。
Spring の SimpleClientHttpRequestFactory
プロキシ設定をより明示的に制御する必要がある場合は、次の例に示すように、Spring の SimpleClientHttpRequestFactory
を使用して「プロキシ」プロパティを設定できます。
<bean id="requestFactory"
class="org.springframework.http.client.SimpleClientHttpRequestFactory">
<property name="proxy">
<bean id="proxy" class="java.net.Proxy">
<constructor-arg>
<util:constant static-field="java.net.Proxy.Type.HTTP"/>
</constructor-arg>
<constructor-arg>
<bean class="java.net.InetSocketAddress">
<constructor-arg value="123.0.0.1"/>
<constructor-arg value="8080"/>
</bean>
</constructor-arg>
</bean>
</property>
</bean>
HTTP ヘッダーマッピング
Spring Integration は、HTTP リクエストと HTTP レスポンスの両方の HTTP ヘッダーマッピングのサポートを提供します。
デフォルトでは、すべての標準 HTTP ヘッダー [Wikipedia] (英語) は、さらに構成することなく、メッセージから HTTP リクエストまたはレスポンスヘッダーにマップされます。ただし、さらにカスタマイズが必要な場合は、ネームスペースのサポートを利用して追加の構成を提供できます。ヘッダー名のコンマ区切りリストを提供でき、ワイルドカードとして機能する "*" 文字を使用した単純なパターンを含めることができます。このような値を指定すると、デフォルトの動作が上書きされます。基本的に、その時点で完全に制御されていることを前提としています。ただし、すべての標準 HTTP ヘッダーを含める場合は、ショートカットパターン HTTP_REQUEST_HEADERS
および HTTP_RESPONSE_HEADERS
を使用できます。次のリストは、2 つの例を示しています(最初の例ではワイルドカードを使用しています)。
<int-http:outbound-gateway id="httpGateway"
url="http://localhost/test2"
mapped-request-headers="thing1, thing2"
mapped-response-headers="X-*, HTTP_RESPONSE_HEADERS"
channel="someChannel"/>
<int-http:outbound-channel-adapter id="httpAdapter"
url="http://localhost/test2"
mapped-request-headers="thing1, thing2, HTTP_REQUEST_HEADERS"
channel="someChannel"/>
アダプターとゲートウェイは DefaultHttpHeaderMapper
を使用します。DefaultHttpHeaderMapper
は、適切な方向を適用できるように、受信と送信のアダプターに 2 つの静的ファクトリメソッドを提供します(HTTP リクエストとレスポンスを適切にマッピングします)。
さらにカスタマイズが必要な場合は、DefaultHttpHeaderMapper
を個別に構成し、header-mapper
属性を介してアダプターに挿入することもできます。
バージョン 5.0 より前の DefaultHttpHeaderMapper
は、ユーザー定義の非標準 HTTP ヘッダーのデフォルトプレフィックスは X-
でした。バージョン 5.0 は、デフォルトのプレフィックスを空の文字列に変更しました。RFC-6648 [IETF] (英語) によると、このようなプレフィックスの使用は現在推奨されていません。DefaultHttpHeaderMapper.setUserDefinedHeaderPrefix()
プロパティを設定することにより、引き続きこのオプションをカスタマイズできます。次の例では、HTTP ゲートウェイのヘッダーマッパーを構成します。
<int-http:outbound-gateway id="httpGateway"
url="http://localhost/test2"
header-mapper="headerMapper"
channel="someChannel"/>
<bean id="headerMapper" class="o.s.i.http.support.DefaultHttpHeaderMapper">
<property name="inboundHeaderNames" value="thing1*, *thing2, thing3"/>
<property name="outboundHeaderNames" value="a*b, d"/>
</bean>
DefaultHttpHeaderMapper
がサポートするもの以外の何かを行う必要がある場合は、HeaderMapper
戦略インターフェースを直接実装し、実装への参照を提供できます。
統合グラフコントローラー
バージョン 4.3 以降、HTTP モジュールは @EnableIntegrationGraphController
構成クラスアノテーションと <int-http:graph-controller/>
XML 要素を提供して、IntegrationGraphServer
を REST サービスとして公開します。詳細については、統合グラフを参照してください。
HTTP サンプル
このセクションでは、Spring Integration の HTTP サポートについてのいくつかの例を挙げて説明します。
マルチパート HTTP リクエスト — RestTemplate(クライアント)および Http 受信ゲートウェイ (サーバー)
この例は、Spring の RestTemplate
でマルチパート HTTP リクエストを送信し、Spring Integration HTTP 受信アダプターで受信することがいかに簡単かを示しています。MultiValueMap
を作成し、マルチパートデータを入力します。RestTemplate
は、それを MultipartHttpServletRequest
に変換することで残りを処理します。この特定のクライアントは、会社の名前とイメージファイル(会社のロゴ)を含むマルチパート HTTP リクエストを送信します。次のリストに例を示します。
RestTemplate template = new RestTemplate();
String uri = "http://localhost:8080/multipart-http/inboundAdapter.htm";
Resource s2logo =
new ClassPathResource("org/springframework/samples/multipart/spring09_logo.png");
MultiValueMap map = new LinkedMultiValueMap();
map.add("company", "SpringSource");
map.add("company-logo", s2logo);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("multipart", "form-data"));
HttpEntity request = new HttpEntity(map, headers);
ResponseEntity<?> httpResponse = template.exchange(uri, HttpMethod.POST, request, null);
クライアントに必要なのはそれだけです。
サーバー側には、次の構成があります。
<int-http:inbound-channel-adapter id="httpInboundAdapter"
channel="receiveChannel"
path="/inboundAdapter.htm"
supported-methods="GET, POST"/>
<int:channel id="receiveChannel"/>
<int:service-activator input-channel="receiveChannel">
<bean class="org.springframework.integration.samples.multipart.MultipartReceiver"/>
</int:service-activator>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
'httpInboundAdapter' はリクエストを受信し、LinkedMultiValueMap
であるペイロードを持つ Message
に変換します。次に、次の例に示すように、"multipartReceiver" サービスアクティベータでそれを解析します。
public void receive(LinkedMultiValueMap<String, Object> multipartRequest){
System.out.println("### Successfully received multipart request ###");
for (String elementName : multipartRequest.keySet()) {
if (elementName.equals("company")){
System.out.println("\t" + elementName + " - " +
((String[]) multipartRequest.getFirst("company"))[0]);
}
else if (elementName.equals("company-logo")){
System.out.println("\t" + elementName + " - as UploadedMultipartFile: " +
((UploadedMultipartFile) multipartRequest
.getFirst("company-logo")).getOriginalFilename());
}
}
}
次の出力が表示されます。
### Successfully received multipart request ###
company - SpringSource
company-logo - as UploadedMultipartFile: spring09_logo.png