Java WebService 完整教程
目录
- 第一部分:基础概念
- 什么是 WebService?
- 为什么使用 WebService?
- WebService 的核心标准(SOAP, WSDL, REST)
- 第二部分:使用 JAX-WS 开发 SOAP WebService
- JAX-WS 简介
- 自上而下(从 WSDL 开始)开发
- 自下而上(从 Java 代码开始)开发 (推荐)
- 发布和调用 WebService
- 第三部分:使用 JAX-RS 开发 RESTful WebService
- REST 架构风格简介
- JAX-RS 简介 (Jakarta RESTful Web Services / JAX-RS)
- 开发一个简单的 RESTful Service
- 使用 Jersey 或 RESTEasy 作为实现
- 第四部分:进阶与总结
- 如何选择 SOAP vs. REST?
- 常见问题与调试技巧
- 总结与学习路径
第一部分:基础概念
什么是 WebService?
WebService 是一种跨编程语言和跨操作系统平台的远程调用技术,它允许你通过 Web 协议(主要是 HTTP)来暴露应用程序的功能,使得其他应用程序可以通过网络来调用这些功能。

WebService 就是一个“网络上的服务”,你可以像调用本地方法一样调用它,但它运行在远程的计算机上。
为什么使用 WebService?
- 跨平台/跨语言:WebService 基于 XML(或 JSON)等标准数据格式,任何支持 HTTP 和 XML/JSON 的语言都可以调用它,Java 可以调用 .NET 的服务,反之亦然。
- 系统解耦:通过 WebService,可以将不同模块、不同系统(如前端、后端、移动 App、第三方系统)连接起来,降低系统间的耦合度。
- 复用现有功能:可以将已有的业务逻辑封装成 WebService,供多个系统复用,避免重复开发。
- B2B 集成:是企业间(Business-to-Business)数据交换和集成的常用标准。
WebService 的核心标准
SOAP (Simple Object Access Protocol)
- 是什么:一种基于 XML 的协议,用于在 Web 上交换结构化的信息,它不仅仅是简单的数据传输,还包括了消息处理、错误处理等机制。
- 特点:
- 重量级:由于 XML 描述的复杂性,SOAP 消息通常比较庞大。
- 标准化:有严格的规范(WS-* 标准),提供了安全性、事务、可靠性等高级特性。
- 平台无关:基于 XML,天生跨平台。
- 使用 WSDL:服务端会提供一个
WSDL(Web Services Description Language) 文件,用来描述服务的接口、方法、参数、返回值等,客户端可以根据 WSDL 生成调用代码。
WSDL (Web Services Description Language)
- 是什么:一个基于 XML 的文件,是 WebService 的“说明书”或“合同”。
- 作用:它详细描述了 WebService 的地址、端口、可用的操作(方法)、每个操作的输入/输出消息格式(数据结构)以及通信协议(如 SOAP/HTTP),客户端工具(如
wsimport)可以解析 WSDL 文件,自动生成客户端存根代码,从而方便地调用服务。
REST (Representational State Transfer)
- 是什么:它不是一种标准,而是一种软件架构风格,由 Roy Fielding 在他的博士论文中提出。
- 特点:
- 轻量级:通常使用 JSON 或 XML 作为数据格式,消息体小,传输效率高。
- 无状态:服务器不保存客户端的状态,每次请求都包含处理该请求所需的所有信息。
- 资源导向:将一切看作“资源”,通过 URI (Uniform Resource Identifier) 来唯一标识资源。
- 统一接口:使用标准的 HTTP 方法(GET, POST, PUT, DELETE)来对资源进行操作。
GET:获取资源POST:创建资源PUT:更新资源(全量)DELETE:删除资源
- 无 WSDL:通常没有 WSDL 文件,API 的描述通过 HTML 文档或 OpenAPI/Swagger 规范来提供。
第二部分:使用 JAX-WS 开发 SOAP WebService
JAX-WS (Java API for XML Web Services) 是 Java 官方定义的一套用于创建 SOAP WebService 的 API,它简化了 SOAP 服务的开发,我们主要关注其注解。
JAX-WS 简介
JAX-WS 提供了丰富的注解,如 @WebService, @WebMethod, @WebParam 等,使得我们可以将一个普通的 Java 类快速转换成一个 WebService 端点。
自下而上(从 Java 代码开始)开发 (推荐)
这是最常用的开发方式,即先编写 Java 代码,然后由工具生成 WSDL 和其他相关文件。

步骤 1:创建 Maven 项目
在 pom.xml 中添加 JAX-WS 的依赖,如果你使用 JDK 9+,需要添加 java.xml.ws 模块。
<dependencies>
<!-- JAX-WS API -->
<dependency>
<groupId>jakarta.xml.ws</groupId>
<artifactId>jakarta.xml.ws-api</artifactId>
<version>3.0.1</version>
</dependency>
<!-- JAX-WS RI (Reference Implementation) - 内置在 JDK 中,但显式引入可以确保一致性 -->
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
<!-- 如果使用 JDK 9+,需要添加 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<compilerArgs>
<arg>--add-modules</arg>
<arg>java.xml.ws</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
步骤 2:创建服务端点接口
这是一个普通的 Java 接口,使用 @WebService 注解来标记它。
// src/main/java/com/example/HelloService.java
package com.example;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService(name = "Hello", // 指定 WSDL 中 <wsdl:portType> 的 name
targetNamespace = "http://example.com/" // 指定命名空间,非常重要
)
public interface HelloService {
/**
* 这是一个 WebService 方法
* @param name 用户名
* @return 问候语
*/
@WebMethod
String sayHello(@WebParam(name = "userName") String name);
}
步骤 3:创建服务端点实现类
这个类实现了上面的接口,是真正的业务逻辑。
// src/main/java/com/example/HelloServiceImpl.java
package com.example;
import javax.jws.WebService;
// endpointInterface 指定它实现了哪个接口
@WebService(endpointInterface = "com.example.HelloService")
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
System.out.println("Server received request for: " + name);
return "Hello, " + name + "! Welcome to JAX-WS World.";
}
}
步骤 4:发布 WebService
我们需要一个主类来启动一个内嵌的 HTTP 服务器并发布我们的服务。

// src/main/java/com/example/WebServicePublisher.java
package com.example;
import javax.xml.ws.Endpoint;
public class WebServicePublisher {
public static void main(String[] args) {
// 定义服务的发布地址
String address = "http://localhost:8080/ws/hello";
// 创建服务的实现实例
HelloService implementor = new HelloServiceImpl();
// 发布服务
Endpoint.publish(address, implementor);
System.out.println("WebService is published at: " + address);
System.out.println("You can access the WSDL at: " + address + "?wsdl");
}
}
步骤 5:运行和测试
-
运行:直接运行
WebServicePublisher的main方法。 -
验证 WSDL:在浏览器中访问
http://localhost:8080/ws/hello?wsdl,如果看到一个 XML 文件,说明服务发布成功。 -
生成客户端代码:
- 打开一个新的命令行窗口。
- 使用 JDK 自带的
wsimport工具,确保你的 JAVA_HOME 指向了 JDK。# -p: 客户端代码的包名 # -keep: 生成的源代码 # -d: 编译后的 .class 文件存放目录 wsimport -p com.example.client -keep -d ./client http://localhost:8080/ws/hello?wsdl
这会在
com/example/client目录下生成一堆.java文件。
-
调用服务: 创建一个新的客户端类来调用服务。
// src/main/java/com/example/client/HelloClient.java package com.example.client; public class HelloClient { public static void main(String[] args) { // 创建服务视图 HelloService_Service service = new HelloService_Service(); // 获取服务端点 HelloService helloPort = service.getHelloPort(); // 调用方法 String response = helloPort.sayHello("WebService User"); System.out.println("Client received response: " + response); } }将
wsimport生成的com/example/client目录下的所有.java文件复制到你的项目中,然后运行HelloClient,即可看到客户端成功调用服务端并打印出结果。
第三部分:使用 JAX-RS 开发 RESTful WebService
JAX-RS (Jakarta RESTful Web Services) 是 Java 官方定义的一套用于创建 RESTful Web 服务的 API,它使用注解来简化资源的定义。
REST 架构风格简介 (回顾)
- 资源:URI 标识,如
/users,/products/123。 - HTTP 方法:GET (读), POST (增), PUT (改), DELETE (删)。
- 数据格式:JSON, XML 等,现代 Web 服务首选 JSON。
JAX-RS 简介
JAX-RS 提供了 @Path, @GET, @POST, @Produces, @Consumes 等注解来定义资源类和方法。
开发一个简单的 RESTful Service
步骤 1:创建 Maven 项目
在 pom.xml 中添加 JAX-RS 的依赖,这里我们使用 Jersey 作为 JAX-RS 的参考实现。
<dependencies>
<!-- JAX-RS API -->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>9.1.0</version>
<scope>provided</scope>
</dependency>
<!-- JAX-RS 实现 - Jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
步骤 2:创建资源类
这是 REST 服务的核心,使用 @Path 注解在类上定义 URI 路径。
// src/main/java/com/example/ResourceConfig.java
package com.example;
import org.glassfish.jersey.server.ResourceConfig;
import jakarta.ws.rs.ApplicationPath;
// 声明这是一个 JAX-RS 应用,并设置根路径
@ApplicationPath("/api")
public class ResourceConfig extends jakarta.ws.rs.core.Application {
// 这里可以注册资源类,但 Jersey 会自动扫描
}
// src/main/java/com/example/GreetingResource.java
package com.example;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
// @Path 定义了这个资源的 URI 路径
@Path("/greetings")
public class GreetingResource {
// @GET 表示这个方法处理 HTTP GET 请求
// @Path("hello") 可以在类路径基础上再添加一层路径
// @Produces 定义了方法返回的媒体类型,这里是 JSON
@GET
@Path("hello")
@Produces(MediaType.APPLICATION_JSON)
public String sayHello() {
return "{\"message\": \"Hello, RESTful World!\"}";
}
// 带有路径参数的例子
@GET
@Path("hello/{name}")
@Produces(MediaType.APPLICATION_JSON)
public String sayHelloTo(@PathParam("name") String name) {
return "{\"message\": \"Hello, " + name + "!\"}";
}
}
步骤 3:配置 Web 服务器 (Tomcat)
你需要一个 Servlet 容器来运行 JAX-RS 应用,我们将使用 Tomcat。
- 下载并安装 Tomcat。
- 将你的 WAR 包部署到 Tomcat 的
webapps目录。 - 为了让 Tomcat 能识别 JAX-RS,我们需要一个
web.xml文件(虽然 Jersey 3.x 可以无配置,但为了清晰,这里展示配置)。
<!-- src/main/webapp/WEB-INF/web.xml -->
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.example</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
jersey.config.server.provider.packages告诉 Jersey 去哪个包下扫描 JAX-RS 资源。<url-pattern>/api/*将所有以/api/开头的请求都交给 Jersey 处理。
步骤 4:打包、部署和测试
- 打包:使用 Maven 打包成 WAR 文件。
mvn clean package
- 部署:将生成的
your-app-name.war复制到 Tomcat 的webapps目录下。 - 启动 Tomcat。
- 测试:
- 在浏览器或使用 Postman 访问:
http://localhost:8080/your-app-name/api/greetings/hellohttp://localhost:8080/your-app-name/api/greetings/hello/Jack
- 你应该能看到返回的 JSON 字符串。
- 在浏览器或使用 Postman 访问:
第四部分:进阶与总结
如何选择 SOAP vs. REST?
| 特性 | SOAP | REST |
|---|---|---|
| 协议 | 严格基于 XML 的协议 | 一种架构风格,通常基于 HTTP |
| 数据格式 | 强制使用 XML | 灵活,常用 JSON, XML, HTML |
| 标准 | 强大且标准化 (WS-*) | 松散,依赖 URI 和 HTTP 标准 |
| 性能 | 较低(XML 解析开销大) | 较高(JSON 解析快,消息体小) |
| 安全性 | 内置且强大的安全机制 (WS-Security) | 通常依赖 HTTPS 和 OAuth2 等标准 |
| 状态 | 无状态或有状态(通过 WS-*) | 强调无状态 |
| 工具与学习曲线 | 工具成熟(WSDL, wsimport),学习曲线较陡 | 简单直观,易于学习和使用 |
| 适用场景 | 企业级应用、金融交易、需要高可靠性和安全性的 B2B 集成 | 公开 API、移动后端、微服务、Web 前端应用 |
简单来说:
- 如果你需要处理复杂的交易、对安全性和可靠性有极高要求,并且需要与 .NET 等非 Java 生态深度集成,SOAP 是一个不错的选择。
- 如果你正在构建一个面向公众的 API、一个微服务系统,或者追求开发速度和性能,REST 是目前的事实标准。
常见问题与调试技巧
- 端口被占用:确保你的 WebService 发布端口没有被其他程序占用。
- 依赖冲突:Maven 项目中容易出现不同版本的依赖冲突,使用
mvn dependency:tree查看。 - 404 Not Found:
- SOAP:检查 WSDL 地址是否正确,
?wsdl参数是否添加。 - REST:检查
@Path注解是否正确,以及 URL 路径是否与@Path完全匹配。
- SOAP:检查 WSDL 地址是否正确,
- 500 Internal Server Error:查看服务端控制台的日志,这是最直接的错误来源。
- CORS 问题:如果你的前端和后端不在同一个域下,浏览器会因为同源策略而阻止请求,需要在服务端配置 CORS 响应头。
总结与学习路径
- 基础:理解 SOAP 和 REST 的核心思想。
- JAX-WS:掌握使用注解 (
@WebService,@WebMethod) 开发和发布 SOAP 服务,并学会使用wsimport生成客户端。 - JAX-RS:掌握使用注解 (
@Path,@GET,@Produces) 开发 RESTful 服务,并理解如何与 Web 容器(如 Tomcat)集成。 - 进阶:
- 数据绑定:学习如何使用 JAXB (SOAP) 或 Jackson/Gson (REST) 来处理复杂的 Java 对象和 XML/JSON 的转换。
- 框架集成:学习如何在 Spring Boot 中集成 JAX-WS 和 JAX-RS,Spring Boot 能极大地简化部署和配置。
- 安全性:学习如何为你的 WebService 添加身份验证和授权。
- 测试:学习使用 Postman, SoapUI 等工具来测试你的 API。
这份教程为你提供了从零开始构建 Java WebService 的完整路径,动手实践是最好的学习方式,祝你学习愉快!
