【问题标题】:How to set timeout in Spring WebServiceTemplate如何在 Spring WebServiceTemplate 中设置超时
【发布时间】:2011-07-18 13:36:22
【问题描述】:

我正在使用org.springframework.ws.client.core.WebServiceTemplate 进行 Web 服务调用。如何配置通话超时。

【问题讨论】:

    标签: java spring spring-ws


    【解决方案1】:

    如果您使用的是 Spring Webservices 2.1.0 版本,您可以使用HttpComponentsMessageSender 设置超时。

    CommonsHttpMessageSender 已被弃用,Spring 不再推荐。

    我实现它的方式是,我将我的 WebServiceTemplate 定义为使用 HttpComponentsMessageSender。

    值以毫秒为单位

    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
        <property name="defaultUri" value="${endpoint.url}" />
        <property name="marshaller" ref="marshaller" />
        <property name="unmarshaller" ref="unmarshaller" />
        <property name="messageSender">
            <bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
                <property name="connectionTimeout" value="1200000" />
                <property name="readTimeout" value="1200000" />
            </bean>
        </property>
    </bean>
    

    只要确保你的 pom 文件中有,你添加了以下内容

    <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.2.1</version>
            <scope>compile</scope>
        </dependency>
    

    【讨论】:

      【解决方案2】:

      与 Sathish 答案相同,但以编程方式(Spring 4+):

      @Component
      public class MyWebServiceGatewaySupport extends WebServiceGatewaySupport
      {
          @Value("${my.ws.readtimeout}")
          private String readTimeout;
      
          @Value("${my.ws.connectiontimeout}")
          private String connectionTimeout;
      
          Object marshalSendAndReceive(String endpoint, Object requestPayload)
          {
      
              WebServiceTemplate wsTemplate = this.getWebServiceTemplate();
              WebServiceMessageSender[] senders = wsTemplate.getMessageSenders();
              for (WebServiceMessageSender sender: senders)
              {
                  try
                  {
                      int readTimeoutMsec = Integer.parseInt(readTimeout);
                      int connTimeoutMsec = Integer.parseInt(connectionTimeout);
                      HttpComponentsMessageSender httpSender = (HttpComponentsMessageSender) sender;
                      httpSender.setReadTimeout(readTimeoutMsec);
                      httpSender.setConnectionTimeout(connTimeoutMsec);
                  }
                  catch (ClassCastException|NumberFormatException cex)
                  {
                       logger.warn("Cannot set WS timeout: " + cex.getMessage());
                  }
              }
      
              return wsTemplate.marshalSendAndReceive(endpoint, requestPayload);
      
           }
       }
      

      【讨论】:

      • 我在我的 Spring Boot 和 Spring WS 项目中已经使用了 Integer 注入,例如@Value("${my.ws.readtimeout}") private Integer readTimeout
      • 我必须在senders 中找到HttpUrlConnectionMessageSender,然后将java.time.Duration.ofMillis() 提供给setter。
      • 出现错误:org.springframework.ws.transport.http.HttpComponentsMessageSender 的 org.apache.http.impl.client.InternalHttpClient.getParams(InternalHttpClient.java:211) 处的 java.lang.UnsupportedOperationException。 setReadTimeout(HttpComponentsMessageSender.java:149)
      【解决方案3】:

      从Spring Webservices 2.2开始,也可以使用Spring的ClientHttpRequestMessageSender

      @Service
      public class CustomWebServiceImpl extends WebServiceGatewaySupport implements CustomWebService {
          private static final int CONNECTION_TIMEOUT = (10 * 1000);
          private static final int READ_TIMEOUT = (10 * 1000);
      
          public CustomWebServiceImpl() {
              SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
              requestFactory.setConnectTimeout(CONNECTION_TIMEOUT);
              requestFactory.setReadTimeout(READ_TIMEOUT);
              setMessageSender(new ClientHttpRequestMessageSender(requestFactory));
          }
      
          (...)
      }
      

      (不需要依赖 Apache HTTP 组件)

      【讨论】:

      • 谢谢@darrachequesne,这解决了我的问题:)
      【解决方案4】:

      下面的代码对我有用。

      @Bean
      public YourClassImpl yourClassImpl(Jaxb2Marshaller marshaller, HttpComponentsMessageSender  httpComponentsMessageSender) {
          YourClassImpl client = new YourClassImpl();
          client.setDefaultUri(PiiProperties.SOAP_ACTION.getValue());
          client.setMarshaller(marshaller);
          client.setUnmarshaller(marshaller);
          client.setMessageSender(httpComponentsMessageSender);
          return client;
      }
      
      @Bean
      public HttpComponentsMessageSender httpComponentsMessageSender() {     
          HttpComponentsMessageSender sender = new HttpComponentsMessageSender();
          sender.setReadTimeout(1000);
          sender.setConnectionTimeout(1000);
          return sender;
      }
      

      【讨论】:

        【解决方案5】:

        【讨论】:

        • 那么,WebServiceTemplate 甚至没有默认超时?通话有效期多久?
        • 是否可以设置每个请求的超时时间?这样我们可以在运行时调整超时时间。
        【解决方案6】:

        我就是这样做的:

        @Configuration
        public class MunisServiceConfig {
        
            @Value("${service.uri}")
            private String soapUri;
        
            @Bean
            Jaxb2Marshaller jaxb2Marshaller() {
                Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
                jaxb2Marshaller.setContextPath(CheckStatePayment.class.getPackage().getName());
        
                return jaxb2Marshaller;
            }
        
            @Bean
            public WebServiceTemplate munisService() {
                WebServiceTemplate template = new WebServiceTemplate();
        
                template.setMarshaller(jaxb2Marshaller());
                template.setUnmarshaller(jaxb2Marshaller());
        
                template.setDefaultUri(soapUri);
        
                HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
                httpComponentsMessageSender.setReadTimeout(3000);
                httpComponentsMessageSender.setConnectionTimeout(5000);
                template.setMessageSender(httpComponentsMessageSender);
        
                return template;
            }
        
        }
        

        【讨论】:

          【解决方案7】:

          这篇文章可能会帮你解决: http://onebyteatatime.wordpress.com/2009/03/19/how-to-set-socket-timeout-using-spring-webservicetemplate/

          按照我的实现方式,我将 WebServiceTemplate 定义为使用 CommonsHttpMessageSender:

          <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
                  <constructor-arg ref="messageFactory" />
                  <property name="messageSender">
                      <bean
                          class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
                      </bean>
                  </property>
          </bean>
          

          然后,在代码中,我获取 messageSender 并在其上设置超时。您同样可以在您的 xml 中执行此操作。

          CommonsHttpMessageSender messageSender = (CommonsHttpMessageSender)webServiceTemplate.getMessageSenders()[0];
          messageSender.getHttpClient().getParams().setSoTimeout(timeoutMillis);
          

          【讨论】:

            【解决方案8】:

            此代码适用于 Spring Boot(在 2.1.5.RELEASE 上验证):

            @Configuration
            public class ExampleServiceClientConfiguration {
            
                @Value("${example-service.uri}")
                private String exampleServiceUri;
            
                @Value("${example-service.timeout:120}")
                private int exampleServiceTimeout;
            
                @Bean
                public ExampleServiceClient exampleServiceClient() {
                    ExampleServiceClient client = new ExampleServiceClient();
                    client.setMessageSender(httpUrlConnectionMessageSender());
                    client.setDefaultUri(exampleServiceUri);
                    client.setMarshaller(marshaller());
                    client.setUnmarshaller(marshaller());
                    return client;
                }
            
                @Bean
                HttpUrlConnectionMessageSender httpUrlConnectionMessageSender() {
                    HttpUrlConnectionMessageSender sender = new HttpUrlConnectionMessageSender();
                    Duration timeout = Duration.ofSeconds(exampleServiceTimeout);
                    sender.setReadTimeout(timeout);
                    sender.setConnectionTimeout(timeout);
                    return sender;
                }
            
                @Bean
                public Jaxb2Marshaller marshaller() {
                    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
                    marshaller.setContextPath(ObjectFactory.class.getPackageName());
                    return marshaller;
                }
            }
            

            【讨论】:

            • 类似的东西也适用于 Spring Boot java var messageSender = new HttpWebServiceMessageSenderBuilder().setReadTimeout(properties.getHttpReadTimeout()).setConnectTimeout(properties.getHttpConnectTimeout()).build(); return builder.setMarshaller(marshaller) .setUnmarshaller(marshaller).additionalMessageSenders(messageSender).build(); builder 来自 WebServiceTemplateBuilder
            【解决方案9】:

            对于CommonsHttpMessageSender,我们可以通过如下方式设置超时时间:

            <bean id="httpParams" class="org.apache.commons.httpclient.params.HttpClientParams">
              <!-- Timeout in milliseconds: in this case 1 minute -->
              <property name="soTimeout" value="60000" />
            </bean>
            
            <bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
                <property name="params" ref="httpParams" />
            </bean>
            
            <!-- Define the message sender used by all web service templates -->
            <bean id="webServiceMessageSender" class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
                <constructor-arg>
                    <ref bean="httpClient"/>
                </constructor-arg>
            </bean>
            

            并将 webServiceMessageSender 引用如下:

            <bean id="genericWebServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
                   <property name="messageSender" ref="webServiceMessageSender"/>
            </bean>
            

            【讨论】:

              猜你喜欢
              • 2017-02-15
              • 2020-11-27
              • 2014-12-14
              • 2011-04-11
              • 1970-01-01
              • 2018-02-24
              • 1970-01-01
              • 1970-01-01
              • 2016-08-15
              相关资源
              最近更新 更多