我想构建一个软网关,所以我将为我的内部系统提供一些spring集成的url,然后我的系统将其发送到实际目标的url。 这是我的代码。这是一个出站网关,我已经在inputchannel标头中设置了https url。
<int:channel id="inputChannel"/>
<int:channel id="outputChannel">
<int:queue capacity="100"/>
</int:channel>
<int-http:outbound-gateway request-channel="inputChannel"
url-expression="headers.dynamicUrl"
http-method-expression="POST"
expected-response-type="java.lang.String"
reply-channel="outputChannel"
charset="UTF-8">
</int-http:outbound-gateway>
我的Java代码就是这样
MessageChannel inputChannel = context.getBean("inputChannel", MessageChannel.class);
PollableChannel outputChannel = context.getBean("outputChannel", PollableChannel.class);
inputChannel.send(msgWithHTTPsUrl);//msg with https Url https://www.example.net
Message<?> replyMesg = outputChannel.receive();
Message<?> toSend = MessageBuilder.withPayload(replyMesg.getPayload()).copyHeadersIfAbsent(replyMesg.getHeaders()).build();
System.out.println(toSend);
return toSend;
,程序可以打印以发送味精。但浏览器无法获得回复。它显示ERR_CONTENT_DECODING_FAILED。 也许https://www.example.net使用gzip压缩。 那么我该如何处理,以便为公司的内部系统建立一个软网关? 谢谢!
现在,我添加了一个休息模板来解决此错误
<int-http:outbound-gateway request-channel="inputChannel"
url-expression="headers.dynamicUrl"
http-method-expression="POST"
expected-response-type="java.lang.String"
reply-channel="outputChannel"
rest-template="restTemplate"
charset="UTF-8">
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="sslFactory" />
</bean>
<bean id="sslFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg ref="httpClient"/>
</bean>
,我设置了忽略服务器端证书的验证,这是我的httpclient的Java代码
@Component("httpClient")
public class HttpClientFactory extends AbstractFactoryBean<HttpClient> {
@Override
public Class<?> getObjectType() {
return HttpClient.class;
}
public HttpClient getInstance() throws Exception {
return createInstance();
}
@Override
protected HttpClient createInstance() throws Exception {
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setSocketTimeout(3000)
.setConnectTimeout(3000)
.setConnectionRequestTimeout(3000)
.setStaleConnectionCheckEnabled(true)
.build();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
TrustStrategy allTrust = new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
};
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, allTrust).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
.setDefaultRequestConfig(defaultRequestConfig).build();
return httpClient;
}
但是当我使用此httpclient时,outbund-gateway会收到4xx / 5xx响应, 我写了一个HttpPost来测试这个httpclient,响应正常。 是我误解了外向网关吗?还是我错过了什么?
我编写测试用例来测试我的Spring集成应用程序,以及我注入到Spring集成中的httpclient。 spring集成应用收到错误回复:
org.springframework.messaging.MessageHandlingException: HTTP request execution failed for URI [https://www.npr.org/]; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request, failedMessage=GenericMessage [payload=byte[0], headers={content-length=0, http_requestMethod=POST, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@3afa4833, httpMethod=POST, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@3afa4833, respUrl=https://www.npr.org/, host=localhost:8080, http_requestUrl=http://localhost:8080/sihttp/mytest, connection=Keep-Alive, id=256ed96e-9c00-ecf4-9d1b-63f37635fb4a, contentType=application/json;charset=UTF-8, accept-encoding=gzip,deflate, user-agent=Apache-HttpClient/4.5.6 (Java/1.8.0_131), timestamp=1544368429831}]
和httpClient访问https://www.npr.org/直接返回成功。测试代码如下:
CloseableHttpClient httpClient = HttpClients.createDefault(); // same httpclinet I inject in outbound gateway's rest-template
HttpPost post=null;
post = new HttpPost("http://localhost:8080/sihttp/mytest"); // this post will goto my spring integration app, in spring integration app, I will map this url to https://www.npr.ogr, and send out in outbound gateway
// post = new HttpPost("https://www.npr.org/"); // npr.org can successful visit in this post
post.setHeader("Content-Type", "application/json;charset=UTF-8");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(6000).setConnectionRequestTimeout(6000)
.setSocketTimeout(6000).build();
post.setConfig(requestConfig);
CloseableHttpResponse httpResponse = httpClient.execute(post);
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
System.out.println(EntityUtils.toString(httpEntity));
}
httpResponse.close();
在春季集成中,httpclient与httpContext执行
HttpResponse httpResponse = this.httpClient.execute(this.httpRequest, this.httpContext);
并在HttpClient中直接执行。
httpClient.execute(post);
这是两个结果不同的原因吗?
答案 0 :(得分:1)
如果故事是关于GZIP的,则应考虑向您的<int-http:outbound-gateway>
注入其他内容:
<xsd:attribute name="request-factory" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Reference to a ClientHttpRequestFactory to be used by the underlying RestTemplate.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.http.client.ClientHttpRequestFactory" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
我的建议是使用HttpComponentsClientHttpRequestFactory
。
如果仍然无法解决问题,请与我们分享整个堆栈跟踪以确定可能遗漏的内容。