动态 url http-outbound-gateway 的动态超时
Dynamic timeout for dynamic url http-outbound-gateway
我有一个 http-outbound-gateway,它使用动态 urls 连接和读取超时
<int-http:outbound-gateway request-channel="request"
reply-channel="response" url-expression="headers.serviceUrl" http-method="POST"
expected-response-type="java.lang.String" charset="UTF-8" request-factory="httpOutboundRequestFactoryBean" message-converters="messageConverterList" header-mapper="headerMapperBean"/>
<bean id="httpOutboundRequestFactoryBean"
class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<property name="readTimeout" value="5000"/>
<property name="connectTimeout" value="1000"/>
</bean>
是否可以根据headers.serviceUrl中定义的url配置特定超时?
我找了一圈,只找到了这个。
一种解决方法是直接使用 RestTemplate 并每次创建一个 RestTemplate 实例并根据 url 动态设置 requestFactory(超时),但也许有一种内置的方法可以做到这一点spring 集成
提前致谢!
编辑:添加答案
我在 http-outbound-gateway 之前添加了这个服务激活器
public class ThreadLocalSample {
public static ThreadLocal<Integer> serviceTimeout = new ThreadLocal<>();
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadLocalSample.class);
public Message<?> setTimeout(final Message<?> message){
final int number = (new Random().nextInt(20 - 1 + 1) + 1)*1000;
serviceTimeout.set(number);
LOGGER.info("Service timeout thread local: "+number);
return message;
}
扩展了 HttpComponentsClientHttpRequestFactory 并使用线程本地超时覆盖合并配置:
public class MyHttpConnectionFactory extends HttpComponentsClientHttpRequestFactory {
private RequestConfig requestConfig;
private static final Logger LOGGER = LoggerFactory.getLogger(MyHttpConnectionFactory.class);
@Override
protected RequestConfig createRequestConfig(final Object client) {
this.requestConfig = super.createRequestConfig(client);
return this.requestConfig;
}
@Override
protected RequestConfig mergeRequestConfig(final RequestConfig clientConfig) {
if (this.requestConfig == null) { // nothing to merge
return clientConfig;
}
final RequestConfig.Builder builder = RequestConfig.copy(clientConfig);
final int connectTimeout = this.requestConfig.getConnectTimeout();
if (connectTimeout >= 0) {
builder.setConnectTimeout(connectTimeout);
}
final int connectionRequestTimeout = this.requestConfig.getConnectionRequestTimeout();
if (connectionRequestTimeout >= 0) {
builder.setConnectionRequestTimeout(connectionRequestTimeout);
}
final int socketTimeout = ThreadLocalSample.serviceTimeout.get();
LOGGER.info("Service timeout: "+socketTimeout);
if (socketTimeout >= 0) {
builder.setSocketTimeout(socketTimeout);
}
return builder.build();
}
}
spring集成流程修改:
<int-http:outbound-gateway request-channel="request"
reply-channel="response" url-expression="headers.serviceUrl" http-method="POST"
expected-response-type="java.lang.String" charset="UTF-8" request-factory="httpOutboundRequestFactoryBean" message-converters="messageConverterList" header-mapper="headerMapperBean"/>
<bean id="httpOutboundRequestFactoryBean"
class="sample.MyHttpConnectionFactory">
<property name="readTimeout" value="5000"/>
<property name="connectTimeout" value="1000"/>
</bean>
嗯,没有,我怀疑我们会在框架中对此事采取任何行动。 Spring 集成完全依赖于 ClientHttpRequestFactory
及其合约。因此,我们最多可以建议的是一些自定义的东西,扩展你的 HttpComponentsClientHttpRequestFactory
.
如果我们查看这个工厂的源代码,我们会发现类似这样的内容:
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpClient client = getHttpClient();
HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
postProcessHttpRequest(httpRequest);
HttpContext context = createHttpContext(httpMethod, uri);
if (context == null) {
context = HttpClientContext.create();
}
// Request configuration not set in the context
if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
// Use request configuration given by the user, when available
RequestConfig config = null;
if (httpRequest instanceof Configurable) {
config = ((Configurable) httpRequest).getConfig();
}
if (config == null) {
config = createRequestConfig(client);
}
if (config != null) {
context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
}
}
因此,每次调用 createRequest()
时,它都会咨询 HttpContext
and/or RequestConfig
之类的内容。
因此,作为满足您要求的解决方案,我建议处理您在提到的 <int-http:outbound-gateway>
之前填充的 ThreadLocal
并从该自定义 createHttpContext()
或 createRequestConfig()
.
我有一个 http-outbound-gateway,它使用动态 urls 连接和读取超时
<int-http:outbound-gateway request-channel="request"
reply-channel="response" url-expression="headers.serviceUrl" http-method="POST"
expected-response-type="java.lang.String" charset="UTF-8" request-factory="httpOutboundRequestFactoryBean" message-converters="messageConverterList" header-mapper="headerMapperBean"/>
<bean id="httpOutboundRequestFactoryBean"
class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<property name="readTimeout" value="5000"/>
<property name="connectTimeout" value="1000"/>
</bean>
是否可以根据headers.serviceUrl中定义的url配置特定超时?
我找了一圈,只找到了这个
一种解决方法是直接使用 RestTemplate 并每次创建一个 RestTemplate 实例并根据 url 动态设置 requestFactory(超时),但也许有一种内置的方法可以做到这一点spring 集成
提前致谢!
编辑:添加答案
我在 http-outbound-gateway 之前添加了这个服务激活器
public class ThreadLocalSample {
public static ThreadLocal<Integer> serviceTimeout = new ThreadLocal<>();
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadLocalSample.class);
public Message<?> setTimeout(final Message<?> message){
final int number = (new Random().nextInt(20 - 1 + 1) + 1)*1000;
serviceTimeout.set(number);
LOGGER.info("Service timeout thread local: "+number);
return message;
}
扩展了 HttpComponentsClientHttpRequestFactory 并使用线程本地超时覆盖合并配置:
public class MyHttpConnectionFactory extends HttpComponentsClientHttpRequestFactory {
private RequestConfig requestConfig;
private static final Logger LOGGER = LoggerFactory.getLogger(MyHttpConnectionFactory.class);
@Override
protected RequestConfig createRequestConfig(final Object client) {
this.requestConfig = super.createRequestConfig(client);
return this.requestConfig;
}
@Override
protected RequestConfig mergeRequestConfig(final RequestConfig clientConfig) {
if (this.requestConfig == null) { // nothing to merge
return clientConfig;
}
final RequestConfig.Builder builder = RequestConfig.copy(clientConfig);
final int connectTimeout = this.requestConfig.getConnectTimeout();
if (connectTimeout >= 0) {
builder.setConnectTimeout(connectTimeout);
}
final int connectionRequestTimeout = this.requestConfig.getConnectionRequestTimeout();
if (connectionRequestTimeout >= 0) {
builder.setConnectionRequestTimeout(connectionRequestTimeout);
}
final int socketTimeout = ThreadLocalSample.serviceTimeout.get();
LOGGER.info("Service timeout: "+socketTimeout);
if (socketTimeout >= 0) {
builder.setSocketTimeout(socketTimeout);
}
return builder.build();
}
}
spring集成流程修改:
<int-http:outbound-gateway request-channel="request"
reply-channel="response" url-expression="headers.serviceUrl" http-method="POST"
expected-response-type="java.lang.String" charset="UTF-8" request-factory="httpOutboundRequestFactoryBean" message-converters="messageConverterList" header-mapper="headerMapperBean"/>
<bean id="httpOutboundRequestFactoryBean"
class="sample.MyHttpConnectionFactory">
<property name="readTimeout" value="5000"/>
<property name="connectTimeout" value="1000"/>
</bean>
嗯,没有,我怀疑我们会在框架中对此事采取任何行动。 Spring 集成完全依赖于 ClientHttpRequestFactory
及其合约。因此,我们最多可以建议的是一些自定义的东西,扩展你的 HttpComponentsClientHttpRequestFactory
.
如果我们查看这个工厂的源代码,我们会发现类似这样的内容:
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpClient client = getHttpClient();
HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
postProcessHttpRequest(httpRequest);
HttpContext context = createHttpContext(httpMethod, uri);
if (context == null) {
context = HttpClientContext.create();
}
// Request configuration not set in the context
if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
// Use request configuration given by the user, when available
RequestConfig config = null;
if (httpRequest instanceof Configurable) {
config = ((Configurable) httpRequest).getConfig();
}
if (config == null) {
config = createRequestConfig(client);
}
if (config != null) {
context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
}
}
因此,每次调用 createRequest()
时,它都会咨询 HttpContext
and/or RequestConfig
之类的内容。
因此,作为满足您要求的解决方案,我建议处理您在提到的 <int-http:outbound-gateway>
之前填充的 ThreadLocal
并从该自定义 createHttpContext()
或 createRequestConfig()
.