Spring webServiceTemplate连接超时属性

时间:2015-06-12 13:08:07

标签: java spring soap

看起来Spring的WebServiceTemplate忽略了连接超时的设置。那,或者我误解了连接超时。

这是我的配置:

@Bean
public SoapTemplate soapTemplate(Jaxb2Marshaller marshaller, WebServiceMessageSender webServiceMessageSender ) {

    SoapTemplate template = new SoapTemplate();
    template.setDefaultUri("some_url");
    template.setMarshaller(marshaller);
    template.setUnmarshaller(marshaller);
    template.setMessageSender(webServiceMessageSender);
    return template;
}

@Bean
public WebServiceMessageSender webServiceMessageSender() {

    HttpComponentsMessageSender sender =  new HttpComponentsMessageSender();

    sender.setReadTimeout(5*1000);
    sender.setConnectionTimeout(5*1000);

    return sender;

}

Soap模板扩展了WebServiceGateway,并具有一些特定的日志记录,自定义异常功能。

当我启动应该接收WebServiceTemplate生成的SOAP消息的目标应用程序时,读取超时按预期工作。如果服务器在指定时间内没有响应,则抛出异常。

我的理解是,如果TCP 3-Way Handshake没有在指定时间内发生,则应该发生连接超时。但事实并非如此,因为超时总是在约2秒后发生,无论我的配置如何。

这是一个有效的测试,还是应该使用在线但不能接受新连接的拥塞服务器测试连接超时?我的客户遇到了哪个超时,可以控制吗?

1 个答案:

答案 0 :(得分:1)

这不能解释问题,但HttpComponentsMessageSender的默认构造函数使用不推荐的org.apache.http.impl.client.DefaultHttpClient。尝试使用org.apache.http.client.HttpClient:

@Bean
public HttpComponentsMessageSender webServiceMessageSender() {

  final HttpClient httpClient = buildHttpClient(5*1000, 5*1000, 2, true);
  final HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(httpClient);
  return messageSender;
}

@SuppressWarnings("resource")
private static HttpClient buildHttpClient(final int connectionTimeout, final int socketTimeout, final int retryCount, final boolean trustAll) {

    // timeout config
    final RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectionTimeout).setSocketTimeout(socketTimeout).build();

    // trust all (if selected)
    SSLConnectionSocketFactory sslSocketFactory = null;
    if (trustAll) {
        try {
            final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustAllStrategy()).build();
            sslSocketFactory = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            throw new RuntimeException("could not initialize SSL context, reason: " + e.getMessage(), e);
        }
    }

    // socket factory
    final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", trustAll ? sslSocketFactory : SSLConnectionSocketFactory.getSocketFactory()).build();

    // retry handler
    final HttpRequestRetryHandler retryHandler = new SimpleRetryHandler(retryCount);

    // build client
    final HttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig)
        .setConnectionManager(new PoolingHttpClientConnectionManager(socketFactoryRegistry)).setRetryHandler(retryHandler)
        .addInterceptorFirst(new RemoveSoapHeadersInterceptor()).build();

    return httpClient;
}

更新:我们在使用SSL连接的项目中使用了自定义buildHttpClient方法。如果您不需要SSL部分,请尝试逐步删除它。