我正在尝试将某种代理实现为数据流的一部分,我希望在入站网关上接收http请求并通过 outbound 网关。我想保留所有查询字符串参数。我的网关配置是:
<int:channel id="searchRequestChannel" />
<int:channel id="searchReplyChannel" />
<int-http:inbound-gateway id="searchRequestInboundGateway"
supported-methods="GET"
request-channel="searchRequestChannel"
reply-channel="searchReplyChannel"
path="/services/normalization"
reply-timeout="50000"
/>
<int-http:outbound-gateway id="searchServiceGateway"
http-method="GET"
request-channel="searchRequestChannel"
url="http://localhost:8080/query"
extract-request-payload="false"
expected-response-type="java.lang.String"
reply-timeout="50000"
charset="UTF-8"
/>
我预计它会如下工作:
客户端向入站网关发送请求 / services / normalization :
GET / services / normalization q = cat&amp; exclude = black
入站网关接收请求并通过 searchRequestChannel 将其发送到出站网关。
出站网关将整个请求发送到外部服务:
获取/查询q = cat&amp; exclude = black
但是在实践中,出站网关发送的空请求不包含任何查询参数:
GET /query
所以我的问题是,通过出站网关发送入站网关接受的http请求的最简单方法是什么。换句话说,如何通过spring集成工具实现简单代理?
答案 0 :(得分:4)
这有点像kludge,但有效; DispatcherServlet
将请求绑定到线程...
<int-http:inbound-gateway id="searchRequestInboundGateway"
supported-methods="GET"
request-channel="searchRequestEnricherChannel"
reply-channel="searchReplyChannel"
path="/services/normalization{queryString}"
reply-timeout="50000"
/>
<int:header-enricher input-channel="searchRequestEnricherChannel" output-channel="searchRequestChannel">
<int:header name="queryString"
expression="T(org.springframework.web.context.request.RequestContextHolder).requestAttributes.request.queryString" />
</int:header-enricher>
然后在出站方面,使用
<int-http:outbound-gateway id="searchServiceGateway"
http-method="GET"
request-channel="searchRequestChannel"
url="http://localhost:8080/query?{queryString}"
encode-uri="false"
extract-request-payload="false"
expected-response-type="java.lang.String"
reply-timeout="50000"
charset="UTF-8">
<uri-variable name="queryString" expression="headers.queryString" />
</int-http:outbound-gateway>
但是,这不适用于2.2.x及更早版本,因为查询字符串在出站端编码(foo=bar&baz=qux
变为foo%3Dbar%26baz%3Dqux
)。在3.0中,我们添加了使用encode-uri="false"
不使用属性对URI进行编码的功能。这在发布中尚未提供,但可以在3.0.0.BUILD-SNAPSHOT
中找到。
修改强>
以上是适用于所有查询字符串的通用解决方案;如果您知道实际参数,另一种解决方案是分别提取每个参数并在出站端重建查询字符串......
<int-http:inbound-gateway ... >
<int-http:header name="foo" expression="#requestParams.foo.get(0)"/>
<int-http:header name="baz" expression="#requestParams.baz.get(0)"/>
</int-http:inbound-gateway>
<int-http:outbound-gateway request-channel="requestChannel"
url="http://localhost:18080/http/receiveGateway?foo={foo}&baz={baz}"
http-method="POST"
expected-response-type="java.lang.String">
<int-http:uri-variable name="foo" expression="headers.foo"/>
<int-http:uri-variable name="baz" expression="headers.baz"/>
</int-http:outbound-gateway>
在入站方面,如果我们将queryString作为第一类表达式变量#queryString
提供,那会更好。
答案 1 :(得分:4)
我自己的解决方法是使用转换器将消息有效负载中的参数(查询字符串参数的映射)转换为准备好的查询字符串并在出站网关中使用 url-expression 以避免查询字符串编码:
<bean id="payloadToQueryString"
class="com.dph.integration.PayloadToQueryStringTransformer" />
<int-http:inbound-gateway id="searchRequestInboundGateway"
supported-methods="GET"
request-channel="searchRequestChannel"
path="/services/normalization"
reply-timeout="50000" />
<int:transformer input-channel="searchRequestChannel"
output-channel="searchGatewayChannel"
ref="payloadToQueryString" method="transform" />
<int-http:outbound-gateway id="searchServiceGateway"
http-method="GET"
request-channel="searchGatewayChannel"
url-expression="'http://localhost:8080/query?' + payload"
expected-response-type="java.lang.String"
reply-timeout="50000"
charset="UTF-8">
</int-http:outbound-gateway>
PayloadToQueryStringTransformer类是:
public class PayloadToQueryStringTransformer extends AbstractTransformer {
@Override
protected Object doTransform(final Message<?> message) throws Exception {
return MessageBuilder
.withPayload(urlEncodeUTF8(((MultiValueMap) message.getPayload()).toSingleValueMap()))
.copyHeaders(message.getHeaders())
.build();
}
private static String urlEncodeUTF8(final String s) {
try {
return URLEncoder.encode(s, "UTF-8");
} catch (final UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
private static String urlEncodeUTF8(final Map<?,?> map) {
final StringBuilder sb = new StringBuilder();
for (final Map.Entry<?,?> entry : map.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(String.format("%s=%s",
urlEncodeUTF8(entry.getKey().toString()),
urlEncodeUTF8(entry.getValue().toString())
));
}
return sb.toString();
}
}