杰瑞科技汇

Java webservice超时如何设置?

下面我将分场景详细介绍如何设置超时,主要涵盖以下几种主流的 WebService 技术栈:

Java webservice超时如何设置?-图1
(图片来源网络,侵删)
  1. JAX-WS (Java API for XML Web Services) - Java 标准规范,主要用于 SOAP WebService。
  2. JAX-RS (Java API for RESTful Web Services) - Java 标准规范,主要用于 RESTful WebService (通常与 Jersey, RESTEasy 等实现一起使用)。
  3. Apache CXF - 一个功能强大的开源框架,同时支持 SOAP 和 REST。
  4. Spring Boot + Spring Web (REST) - 现代 Java 开发中最主流的 RESTful 服务框架。

JAX-WS (SOAP WebService)

在 JAX-WS 中,客户端超时主要通过 javax.xml.ws.WebServiceFeaturejavax.xml.ws.BindingProvider 来设置。

客户端设置超时

主要有两个超时参数需要设置:

  • javax.xml.ws.http.connection.timeout: 底层 HTTP 连接建立的超时时间(单位:毫秒),如果在这个时间内无法建立连接,就会抛出异常。
  • javax.xml.ws.client.receive.timeout: 从服务器接收响应数据的超时时间(单位:毫秒),如果在这个时间内没有收到任何数据,就会抛出异常。

示例代码:

假设你有一个通过 wsimport 工具生成的客户端存根 MyService

Java webservice超时如何设置?-图2
(图片来源网络,侵删)
import javax.xml.ws.BindingProvider;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.SOAPBinding;
public class JaxWsClientTimeoutExample {
    public static void main(String[] args) {
        // 1. 创建服务客户端
        MyService service = new MyService();
        MyServicePortType port = service.getMyServicePort(); // 获取服务端口
        // 2. 获取 BindingProvider
        BindingProvider bindingProvider = (BindingProvider) port;
        // 3. 设置超时时间(单位:毫秒)
        // 连接超时: 5秒
        int connectTimeout = 5000;
        // 读取超时: 10秒
        int receiveTimeout = 10000;
        // 4. 设置请求属性
        bindingProvider.getRequestContext().put(
            javax.xml.ws.http.connection.timeout, connectTimeout);
        bindingProvider.getRequestContext().put(
            javax.xml.ws.client.receive.timeout, receiveTimeout);
        // 5. 调用WebService
        try {
            String result = port.someMethod("some-param");
            System.out.println("调用成功: " + result);
        } catch (Exception e) {
            System.err.println("调用WebService超时或失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

使用 WebServiceFeature (更现代的方式):

import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.AddressingFeature;
import javax.xml.ws.soap.MTOMFeature;
import javax.xml.ws.soap.SOAPBinding;
public class JaxWsClientTimeoutFeatureExample {
    public static void main(String[] args) {
        MyService service = new MyService();
        // 创建一个带有超时设置的 SOAPBinding 特性
        // 注意:SOAPBinding.setProperty() 是另一种方式,但 BindingProvider 的方式更标准
        WebServiceFeature feature = new SOAPBindingFeature(); // 或者其他特性
        // 获取端口时,可以传入特性
        // MyServicePortType port = service.getMyServicePort(feature);
        // 更推荐的方式还是通过 BindingProvider
        MyServicePortType port = service.getMyServicePort();
        BindingProvider bp = (BindingProvider) port;
        // 设置超时
        bp.getRequestContext().put(SOAPBinding.HTTP_CONNECTION_TIMEOUT, 5000); // 连接超时
        bp.getRequestContext().put(SOAPBinding.HTTP_RECEIVE_TIMEOUT, 10000);  // 读取超时
    }
}

服务器端设置超时

服务器端超时通常在 Web 容器(如 Tomcat)或应用服务器(如 WebSphere, WebLogic)中配置,在 Tomcat 的 context.xml 中为特定的 Servlet 设置超时。

<!-- Tomcat context.xml -->
<Context>
    <!-- 为部署在此 Context 下的所有 Servlet 设置会话超时 (分钟) -->
    <Manager sessionTimeout="30" />
    <!-- 如果使用 Servlet 3.0+ 的异步处理,可以设置异步超时 -->
    <!-- <AsyncTimeout>30000</AsyncTimeout> -->
</Context>

对于 JAX-WS 端点,服务器端超时通常由容器管理,而不是 JAX-WS API 直接控制。


JAX-RS (RESTful WebService)

JAX-RS 本身不直接定义超时,它依赖于底层的 HTTP 客户端实现,常见的实现是 Jersey 和 RESTEasy。

Java webservice超时如何设置?-图3
(图片来源网络,侵删)

使用 Jersey 客户端设置超时

Jersey 客户端提供了 ClientConfig 来配置连接和读取超时。

Maven 依赖:

<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>3.1.0</version> <!-- 使用合适的版本 -->
</dependency>

示例代码:

import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
public class JerseyClientTimeoutExample {
    public static void main(String[] args) {
        // 1. 创建 ClientConfig
        ClientConfig config = new ClientConfig();
        // 2. 设置超时(单位:毫秒)
        // 连接超时: 5秒
        config.property(ClientProperties.CONNECT_TIMEOUT, 5000);
        // 读取超时: 10秒
        config.property(ClientProperties.READ_TIMEOUT, 10000);
        // 3. 使用配置创建 Client
        Client client = ClientBuilder.newClient(config);
        // 4. 创建 WebTarget 并调用服务
        WebTarget target = client.target("http://example.com/api/resource");
        try {
            Response response = target.request().get();
            if (response.getStatus() == 200) {
                String entity = response.readEntity(String.class);
                System.out.println("调用成功: " + entity);
            } else {
                System.out.println("调用失败,状态码: " + response.getStatus());
            }
        } catch (Exception e) {
            System.err.println("调用REST服务超时或失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 5. 关闭客户端
            client.close();
        }
    }
}

使用 RESTEasy 客户端设置超时

RESTEasy 的配置与 Jersey 非常相似,也是通过客户端配置对象设置。

Maven 依赖:

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-client</artifactId>
    <version>6.2.0.Final</version> <!-- 使用合适的版本 -->
</dependency>

示例代码:

import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
import jakarta.ws.rs.core.Response;
public class ResteasyClientTimeoutExample {
    public static void main(String[] args) {
        // 1. 创建 ResteasyClientBuilder
        ResteasyClientBuilder builder = new ResteasyClientBuilder();
        // 2. 设置超时(单位:毫秒)
        // 连接超时: 5秒
        builder.connectTimeout(5, TimeUnit.SECONDS);
        // 读取超时: 10秒
        builder.readTimeout(10, TimeUnit.SECONDS);
        // 3. 构建 Client
        ResteasyClient client = builder.build();
        // 4. 创建 Target 并调用
        ResteasyWebTarget target = client.target("http://example.com/api/resource");
        try {
            Response response = target.request().get();
            if (response.getStatus() == 200) {
                String entity = response.readEntity(String.class);
                System.out.println("调用成功: " + entity);
            } else {
                System.out.println("调用失败,状态码: " + response.getStatus());
            }
        } catch (Exception e) {
            System.err.println("调用REST服务超时或失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 5. 关闭客户端
            client.close();
        }
    }
}

Apache CXF (SOAP & REST)

CXF 是一个非常灵活的框架,它既可以用于 SOAP 也可以用于 REST。

CXF 客户端

分享:
扫描分享到社交APP
上一篇
下一篇