在 Java WebService 的世界里,“对象”通常指代两种核心实体:

- 客户端(Consumer):调用远程服务的应用程序。
- 服务端(Provider):提供服务的应用程序。
这两个“对象”通过标准的 WebService 协议(如 SOAP 或 RESTful)进行交互,下面我将分点详细阐述,并重点介绍如何在这些对象之间传递自定义的 Java 对象。
核心概念:客户端 vs. 服务端
1 WebService 服务端
服务端是“生产者”,它定义了一个或多个可以被远程调用的方法,这些方法可以接收参数、执行业务逻辑,并返回结果,这些参数和结果可以是基本数据类型(如 String, int),也可以是复杂的自定义 Java 对象。
主要技术栈:
- JAX-WS (Java API for XML Web Services):这是 Java 官方、标准的 SOAP WebService 开发框架,非常成熟稳定,广泛用于企业级应用。
- JAX-RS (Java API for RESTful Web Services):这是用于开发 RESTful 风格 WebService 的标准,虽然更侧重于资源,但它也是 WebService 的一种重要形式,并且处理对象的方式与 JAX-WS 不同。
2 WebService 客户端
客户端是“消费者”,它通过网络找到服务端,调用其提供的方法,并处理返回的结果,客户端需要知道服务端的“地址”和“接口规范”(即 WSDL 文件)才能正确地调用。

主要技术栈:
- JAX-WS 客户端:通常通过
wsimport工具根据 WSDL 文件生成客户端代码(存根/代理),然后像调用本地方法一样调用远程方法。 - JAX-RS 客户端:通常使用 Jersey、RestEasy 等框架提供的 API,通过 HTTP 请求(如 GET, POST, PUT, DELETE)来访问 REST 资源。
核心问题:如何在 WebService 中传递 Java 对象?
这是问题的核心,由于 WebService 是基于网络通信的,而网络只能传输文本(如 XML 或 JSON),因此不能直接传输 Java 对象,必须将 Java 对象序列化成一种标准格式的文本,传输到对方后,再反序列化成对方语言(通常是 Java)的对象。
1 基于 SOAP (JAX-WS) 的对象传递
SOAP 协议默认使用 XML 作为数据交换格式,JAX-WS 框架会自动处理 Java 对象与 XML 之间的转换,这个过程称为 XML Binding。
工作原理:

- 服务端:你定义一个方法,参数是一个自定义的 Java 对象(
User对象),JAX-WS 在处理请求时,会自动将这个User对象序列化为符合特定 Schema(XSD)的 XML 文档。 - 网络传输:这个 XML 文档作为 SOAP 消息的一部分被发送给客户端。
- 客户端:客户端接收到 SOAP 消息后,JAX-WS 会根据 WSDL 中定义的 Schema,自动将 XML 文档反序列化成对应的
User对象。
关键步骤:
-
创建 Java 对象 (POJO): 这个对象必须是一个标准的 JavaBean,即有无参构造函数,并且属性有
getter和setter方法。// User.java public class User { private String name; private int age; // 必须有无参构造函数 public User() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } -
在服务端接口中使用该对象: 使用
@WebService注解定义服务端接口。import javax.jws.WebService; import javax.jws.WebMethod; @WebService public interface UserService { @WebMethod public String getGreeting(User user); } -
实现服务端接口:
import javax.jws.WebService; @WebService(endpointInterface = "com.example.UserService") public class UserServiceImpl implements UserService { @Override public String getGreeting(User user) { return "Hello, " + user.getName() + "! You are " + user.getAge() + " years old."; } } -
发布服务: 使用
Endpoint类将服务发布到某个 URL。import javax.xml.ws.Endpoint; public class Publisher { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); Endpoint.publish("http://localhost:8080/userService", userService); System.out.println("UserService is published at http://localhost:8080/userService"); } } -
客户端调用:
-
生成客户端代码:在命令行运行
wsimport -keep http://localhost:8080/userService?wsdl,这会生成一堆 Java 文件,包括一个User类(和你的类同名或类似)和一个UserService接口。 -
使用客户端代码:
import com.example.UserService; import com.example.User; import javax.xml.ws.Service; import java.net.URL; public class Client { public static void main(String[] args) throws Exception { URL wsdlUrl = new URL("http://localhost:8080/userService?wsdl"); QName qname = new QName("http://example.com/", "UserService"); Service service = Service.create(wsdlUrl, qname); UserService userService = service.getPort(UserService.class); // 创建客户端 User 对象 User user = new User(); user.setName("Alice"); user.setAge(30); // 调用远程方法,对象会自动序列化 String response = userService.getGreeting(user); System.out.println(response); // 输出: Hello, Alice! You are 30 years old. } }
-
2 基于 RESTful (JAX-RS) 的对象传递
RESTful WebService 通常使用 JSON 作为数据交换格式,因为它比 XML 更轻量、更易于解析,JAX-RS 框架(如 Jersey)会自动处理 Java 对象与 JSON 之间的转换。
工作原理:
- 服务端:你定义一个资源方法,接收一个 JSON 格式的请求体,JAX-RS 框架(如 Jackson, Gson)会自动将这个 JSON 字符串反序列化成 Java 对象。
- 网络传输:HTTP 请求的 Body 部分是 JSON 格式的数据。
- 服务端返回:方法返回一个 Java 对象,JAX-RS 框架会自动将其序列化为 JSON 字符串,并作为 HTTP 响应的 Body 发送给客户端。
关键步骤 (以 Jersey 为例):
-
添加依赖:确保你的项目包含 Jersey 和 JSON 处理库(如
jersey-media-json-jackson)的依赖。 -
创建 Java 对象 (POJO):和 JAX-WS 一样,需要一个标准的 JavaBean。
// User.java public class User { private String name; private int age; public User() {} // getters and setters... } -
创建资源类: 使用
@Path,@POST,@Consumes,@Produces等注解。import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @Path("/users") public class UserResource { // 接收一个 JSON,并将其映射为 User 对象 @POST @Consumes(MediaType.APPLICATION_JSON) // 声明接收 JSON @Produces(MediaType.APPLICATION_JSON) // 声明返回 JSON public Response createUser(User user) { // 业务逻辑... System.out.println("Received user: " + user.getName()); // 返回一个创建成功的响应,可以包含新创建的用户信息 user.setName("Created: " + user.getName()); return Response.status(201).entity(user).build(); } } -
客户端调用: 客户端可以使用 Jersey 客户端 API、Apache HttpClient 或其他 HTTP 客户端工具。
import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; public class RestClient { public static void main(String[] args) { Client client = ClientBuilder.newClient(); // 创建要发送的 User 对象 User user = new User(); user.setName("Bob"); user.setAge(25); // 发送 POST 请求,User 对象会被自动序列化为 JSON Response response = client.target("http://localhost:8080/myapp/users") .request(MediaType.APPLICATION_JSON) .post(Entity.json(user)); // 从响应中获取返回的 User 对象(自动从 JSON 反序列化) User createdUser = response.readEntity(User.class); System.out.println("Status: " + response.getStatus()); System.out.println("Created User: " + createdUser.getName()); response.close(); client.close(); } }
总结与对比
| 特性 | JAX-WS (SOAP) | JAX-RS (RESTful) |
|---|---|---|
| 协议 | SOAP (XML) | HTTP (通常用 JSON) |
| 数据格式 | XML | JSON (也支持 XML, HTML等) |
| 核心思想 | 动作导向 (RPC-like) | 资源导向 |
| 对象传递 | 自动与 XML 序列化/反序列化 | 自动与 JSON 序列化/反序列化 |
| 客户端调用 | wsimport 生成客户端存根 |
直接使用 HTTP 客户端 API |
| 优点 | 标准化、安全、有契约 (WSDL) | 简单、轻量、易于与前端集成 |
| 缺点 | 协议复杂、冗余 | 无统一标准,依赖具体实现 |
| 适用场景 | 企业级应用、B2B 集成、需要强契约和安全的场景 | 移动应用、前后端分离、微服务 |
重要注意事项
- 对象的可序列化:对于 JAX-WS 和 JAX-RS,你的 JavaBean 最好实现
java.io.Serializable接口,虽然不总是强制要求,但这是一个好习惯,尤其是在涉及分布式系统时。 - 循环引用:如果你的对象图中有循环引用(A 包含 B,B 又包含 A),序列化时可能会栈溢出或陷入死循环,需要小心设计对象结构,或在某些框架中配置处理循环引用的策略。
- 版本兼容性:如果服务端的
User类发生了结构变化(比如新增了一个字段),而客户端没有更新,可能会导致反序列化失败,在设计 API 时应考虑向后兼容性。 - 安全性:在网络上传输对象数据时,特别是敏感信息,务必使用 HTTPS 加密传输,以防止数据被窃听或篡改。
希望这个详细的解释能帮助你全面理解 Java WebService 中的“对象”概念及其交互方式。
