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

- JAX-WS (Java API for XML Web Services) - Java 标准规范,主要用于 SOAP WebService。
- JAX-RS (Java API for RESTful Web Services) - Java 标准规范,主要用于 RESTful WebService (通常与 Jersey, RESTEasy 等实现一起使用)。
- Apache CXF - 一个功能强大的开源框架,同时支持 SOAP 和 REST。
- Spring Boot + Spring Web (REST) - 现代 Java 开发中最主流的 RESTful 服务框架。
JAX-WS (SOAP WebService)
在 JAX-WS 中,客户端超时主要通过 javax.xml.ws.WebServiceFeature 和 javax.xml.ws.BindingProvider 来设置。
客户端设置超时
主要有两个超时参数需要设置:
javax.xml.ws.http.connection.timeout: 底层 HTTP 连接建立的超时时间(单位:毫秒),如果在这个时间内无法建立连接,就会抛出异常。javax.xml.ws.client.receive.timeout: 从服务器接收响应数据的超时时间(单位:毫秒),如果在这个时间内没有收到任何数据,就会抛出异常。
示例代码:
假设你有一个通过 wsimport 工具生成的客户端存根 MyService。

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。

使用 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。
