杰瑞科技汇

Java WebService教程怎么学?入门到实战怎么走?

Java Web Service 完整教程

目录

  1. 第一部分:基础概念
    • 什么是 Web Service?
    • 为什么使用 Web Service?
    • Web Service 的核心特点(SOAP vs. REST)
  2. 第二部分:SOAP Web Service
    • 核心概念:SOAP, WSDL, UDDI
    • 使用 JAX-WS (Java API for XML Web Services) 开发 SOAP Service
      • 自上而下 (Top-Down)
      • 自下而上 (Bottom-Up) - 推荐
    • 使用 CXF 框架发布和调用 SOAP Service
  3. 第三部分:RESTful Web Service
    • 什么是 REST?
    • RESTful API 的核心原则
    • 使用 JAX-RS (Java API for RESTful Web Services) 开发 RESTful Service
      • 入门示例:使用 Jersey 框架
      • 常用注解详解
      • 处理不同数据格式(JSON, XML)
  4. 第四部分:实战项目
    • 项目概述:用户管理 RESTful API
    • 环境搭建
    • 实现步骤
  5. 第五部分:进阶与总结
    • 选择 SOAP 还是 REST?
    • 常用框架对比
    • 安全性、性能与监控
    • 总结与学习资源

第一部分:基础概念

什么是 Web Service?

Web Service 是一种基于 Web 的、跨平台的、跨语言的应用程序交互技术,它允许不同的应用程序在不同的操作系统上,使用不同的编程语言进行通信和交换数据。

Java WebService教程怎么学?入门到实战怎么走?-图1
(图片来源网络,侵删)

你可以把它想象成一个“网络上的函数调用”,你的本地应用(比如一个网站或手机 App)可以通过网络调用一个远程服务器上的服务,获取数据或执行某个操作,就像调用本地方法一样简单。

为什么使用 Web Service?

  • 跨平台和跨语言:服务端可以用 Java 写,客户端可以用 Python、C#、JavaScript 写,只要它们都遵循相同的通信协议。
  • 松耦合:客户端和服务端是独立的,可以独立开发和部署,一方升级或改变,只要接口不变,另一方通常不受影响。
  • 可复用性:一个通用的服务(如天气预报、用户认证)可以被多个不同的应用调用。
  • 基于标准:依赖于 HTTP、XML、JSON 等开放标准,易于理解和实现。

Web Service 的核心特点:SOAP vs. REST

这是 Web Service 两种最主流的实现风格。

特性 SOAP (Simple Object Access Protocol) REST (Representational State Transfer)
协议 严格的协议,基于 XML,有自己的规范(信封、头、体)。 不是协议,而是一种架构风格,基于 HTTP 协议。
数据格式 强制使用 XML。 灵活,常用 JSON、XML、Text 等,JSON 更常见。
标准 有自己的标准,如 WS-Security, WS-Addressing。 遵循 HTTP 标准(GET, POST, PUT, DELETE 等)。
接口定义 使用 WSDL (Web Services Description Language) 文件描述接口。 通常没有明确的接口定义文件,通过 URL 和 HTTP 动词来定义。
重量级 较为重量级,消息头和结构复杂,开销大。 轻量级,简单直接,开销小。
适用场景 企业级应用、需要高安全性、事务性、可靠性的场景(如银行、金融)。 公开 API、移动应用、Web 前后端分离、微服务。

第二部分:SOAP Web Service (使用 JAX-WS)

JAX-WS 是 Java 官方定义的用于创建 SOAP Web Service 的 API。

核心概念

  • SOAP (Simple Object Access Protocol):一种基于 XML 的协议,用于在 Web 上交换结构化信息,它定义了一个消息框架,包括一个信封、一组编码规则、表示数据类型约定以及表示过程调用和响应的约定。
  • WSDL (Web Services Description Language):一个 XML 文件,用于描述 Web Service 的功能,它告诉客户端:服务在哪里(URL)、叫什么名字、可以调用哪些方法、每个方法需要什么参数、返回什么类型的数据。
  • UDDI (Universal Description, Discovery, and Integration):一个目录服务,用于发布和发现 Web Service,现在使用较少,我们通常直接提供 WSDL 文档。

实现方式:自下而上 - 推荐方式

这是最常见的方式,即先编写 Java 代码,然后由工具自动生成 WSDL。

Java WebService教程怎么学?入门到实战怎么走?-图2
(图片来源网络,侵删)
步骤 1:创建 Maven 项目并添加依赖

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>soap-service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- JAX-WS API -->
        <dependency>
            <groupId>javax.xml.ws</groupId>
            <artifactId>jaxws-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <!-- JAX-WS RI (Reference Implementation) -->
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>2.3.3</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- Maven 插件,用于将类编译成 Service -->
            <plugin>
                <groupId>org.jvnet.jax-ws-commons</groupId>
                <artifactId>jaxws-maven-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>wsimport</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sourceSourceDir>src/main/java</sourceSourceDir>
                    <keep>true</keep>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
步骤 2:创建 Service Endpoint Interface (SEI)

这是一个 Java 接口,定义了 Web Service 将要暴露的方法。

src/main/java/com/example/HelloService.java:

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// @WebService 注解表明这是一个 Web Service
@WebService
// @SOAPBinding(style = SOAPBinding.Style.RPC) 表示 RPC 风格,默认是 DOCUMENT
public interface HelloService {
    // @WebMethod 注解将此方法暴露为 Web Service 的一个操作
    @WebMethod
    String sayHello(@WebParam(name = "name") String name);
}
步骤 3:创建 Service Implementation Bean (SIB)

这是实现 SEI 接口的类。

Java WebService教程怎么学?入门到实战怎么走?-图3
(图片来源网络,侵删)

src/main/java/com/example/HelloServiceImpl.java:

import javax.jws.WebService;
// @WebService(endpointInterface = "com.example.HelloService") 指定实现的接口
@WebService(endpointInterface = "com.example.HelloService")
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name + "!";
    }
}
步骤 4:发布 Web Service

我们可以编写一个 main 方法来发布服务,也可以部署到 Servlet 容器(如 Tomcat)中。

src/main/java/com/example/Publisher.java:

import javax.xml.ws.Endpoint;
import com.example.HelloServiceImpl;
public class Publisher {
    public static void main(String[] args) {
        // 创建服务的实现实例
        HelloServiceImpl helloService = new HelloServiceImpl();
        // 发布服务到指定地址
        // 第一个参数是服务的访问地址,第二个参数是服务的实现对象
        Endpoint.publish("http://localhost:8888/hello", helloService);
        System.out.println("SOAP Web Service is published at http://localhost:8888/hello?wsdl");
    }
}

运行 Publisher 类,你的 SOAP 服务就启动了。

步骤 5:测试服务
  1. 在浏览器中访问 http://localhost:8888/hello?wsdl,你会看到一个 XML 文件,这就是 WSDL,它描述了你的服务。
  2. 使用工具测试,如 SoapUI 或 Postman。
    • 在 SoapUI 中,创建新的 SOAP Project,将 WSDL 的 URL 粘贴进去。
    • 工具会自动解析出 sayHello 操作。
    • 在请求中填入参数(<name>World</name>),然后发送请求,你会收到 <return>Hello, World!</return> 的响应。

第三部分:RESTful Web Service (使用 JAX-RS)

REST 架构风格是目前 Web Service 的主流,尤其适用于移动端和前后端分离的项目。

核心概念

  • 资源:在 REST 中,一切皆资源,每个资源都有一个唯一的 URI(统一资源标识符),用户资源可以是 /users,特定用户可以是 /users/123
  • 统一接口:使用标准的 HTTP 方法来操作资源。
    • GET:获取资源
    • POST:创建新资源
    • PUT:更新资源(全量更新)
    • DELETE:删除资源
    • PATCH:部分更新资源
  • 无状态:服务器不保存客户端的状态,每个请求都必须包含处理该请求所需的所有信息。
  • 表现层:资源可以有多种表现形式,如 JSON、XML、HTML 等,客户端通过 Accept 请求头告诉服务器它希望接收哪种格式,服务器通过 Content-Type 响应头告诉客户端它返回的是什么格式。

实现方式:使用 Jersey 框架

Jersey 是 JAX-RS 规范最流行的参考实现之一。

步骤 1:创建 Maven 项目并添加依赖

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>rest-service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- Jersey 核心依赖 -->
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
            <version>2.35</version>
        </dependency>
        <!-- 支持 JSON -->
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-binding</artifactId>
            <version>2.35</version>
        </dependency>
    </dependencies>
</project>
步骤 2:创建资源类

这是一个普通的 Java 类,用 JAX-RS 注解来映射到 URI 和 HTTP 方法。

src/main/java/com/example/Resource.java:

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
// @Path 注解定义了这个类的 URI 基础路径
@Path("/hello")
public class Resource {
    // @GET 注解表示这个方法处理 HTTP GET 请求
    // @Produces 注解指定该方法返回的媒体类型
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getPlainText() {
        return "Hello, World in Plain Text!";
    }
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getJson() {
        // 在实际应用中,这里会返回一个对象,Jersey 会自动将其转换为 JSON
        return "{\"message\": \"Hello, World in JSON!\"}";
    }
    // 路径参数
    @GET
    @Path("/{name}")
    @Produces(MediaType.TEXT_PLAIN)
    public sayHelloToName(@PathParam("name") String name) {
        return "Hello, " + name + "!";
    }
    // 处理 POST 请求
    @POST
    @Path("/echo")
    @Consumes(MediaType.APPLICATION_JSON) // 指定该方法能接受的媒体类型
    @Produces(MediaType.APPLICATION_JSON)
    public Response echoJson(String jsonInput) {
        // 在实际应用中,这里会解析 jsonInput,处理业务逻辑,然后返回结果
        System.out.println("Received JSON: " + jsonInput);
        String responseJson = "{\"status\": \"success\", \"received\": " + jsonInput + "}";
        // 返回一个 Response 对象,可以设置状态码等
        return Response.status(200).entity(responseJson).build();
    }
}
步骤 3:启动服务

src/main/java/com/example/Main.java:

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.net.URI;
public class Main {
    // 定义服务的基地 URI
    public static final String BASE_URI = "http://localhost:8080/myapp/";
    public static void main(String[] args) {
        // 创建一个 ResourceConfig 实例,并注册我们的资源类
        ResourceConfig config = new ResourceConfig().packages("com.example");
        // 创建并启动 Grizzly HTTP 服务器
        HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), config);
        System.out.println("Jersey app started with WADL available at "
                + BASE_URI + "application.wadl\nHit enter to stop it...");
        try {
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            server.shutdownNow();
        }
    }
}
步骤 4:测试服务

运行 Main 类,然后使用 Postman 或浏览器进行测试。

  • GET http://localhost:8080/myapp/hello -> 返回纯文本
  • GET http://localhost:8080/myapp/hello (在 Postman 中设置 Accept 为 application/json) -> 返回 JSON
  • GET http://localhost:8080/myapp/hello/Alice -> 返回 "Hello, Alice!"
  • POST http://localhost:8080/myapp/hello/echo
    • 在 Body 中选择 raw -> JSON,输入: {"user": "Bob"}
    • 设置 Content-Type 为 application/json
    • 发送请求,服务器会返回: {"status": "success", "received": {"user": "Bob"}}

第四部分:实战项目 - 用户管理 RESTful API

我们将创建一个简单的内存版用户管理 API。

  1. 环境:继续使用 Jersey + Maven 项目。
  2. 依赖pom.xml 与上面 REST 示例相同。
  3. 模型User.java
    public class User {
        private int id;
        private String name;
        private String email;
        // 构造器、Getters、Setters、toString()
        // 为了简化,省略了 Lombok
        public User(int id, String name, String email) {
            this.id = id;
            this.name = name;
            this.email = email;
        }
        // ... getters and setters
    }
  4. 资源UserResource.java
    import javax.ws.rs.*;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;

@Path("/users") public class UserResource {

private static List<User> users = new ArrayList<>();
static {
    users.add(new User(1, "Alice", "alice@example.com"));
    users.add(new User(2, "Bob", "bob@example.com"));
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<User> getAllUsers() {
    return users;
}
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUserById(@PathParam("id") int id) {
    User user = users.stream()
            .filter(u -> u.getId() == id)
            .findFirst()
            .orElse(null);
    if (user == null) {
        // 返回 404 Not Found
        return Response.status(Response.Status.NOT_FOUND).build();
    }
    return Response.ok(user).build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createUser(User newUser) {
    // 简单起见,假设新用户没有 ID
    int newId = users.stream().mapToInt(User::getId).max().orElse(0) + 1;
    newUser.setId(newId);
    users.add(newUser);
    // 返回 201 Created,并包含新创建的用户
    return Response.status(Response.Status.CREATED).entity(newUser).build();
}
@DELETE
@Path("/{id}")
public Response deleteUser(@PathParam("id") int id) {
    boolean removed = users.removeIf(u -> u.getId() == id);
    if (removed) {
        return Response.noContent().build(); // 204 No Content
    } else {
        return Response.status(Response.Status.NOT_FOUND).build();
    }
}
```
  1. 启动:使用与 Main.java 相同的代码启动服务。
  2. 测试
    • GET http://localhost:8080/myapp/users -> 获取所有用户列表。
    • POST http://localhost:8080/myapp/users -> Body: {"name": "Charlie", "email": "charlie@example.com"},返回新创建的用户(包含 ID)。
    • GET http://localhost:8080/myapp/users/3 -> 获取 ID 为 3 的用户。
    • DELETE http://localhost:8080/myapp/users/1 -> 删除 ID 为 1 的用户。

第五部分:进阶与总结

选择 SOAP 还是 REST?

  • 选择 SOAP

    • 你需要处理复杂的交易(如银行转账)。
    • 需要高级的 WS-* 标准(如 WS-Security, WS-ReliableMessaging)。
    • 你的公司或合作伙伴已经广泛使用 SOAP。
    • 你需要一个强契约(WSDL)来严格定义接口。
  • 选择 REST

    • 你正在开发公开 API 供移动端或前端使用。
    • 你追求简单、轻量和性能。
    • 你需要利用 HTTP 的特性(如缓存、重定向)。
    • 你的应用是微服务架构的一部分。

目前超过 90% 的新 Web Service 项目会选择 RESTful 风格。

常用框架对比

类型 SOAP REST
核心 API JAX-WS JAX-RS
SOAP 实现 Apache CXF, Metro (GlassFish) -
REST 实现 - Jersey (Reference), RESTEasy (JBoss/WildFly), Apache CXF (也支持 REST)

对于 REST,Jersey 和 RESTEasy 是最主流的选择,Spring Boot 也内置了对 JAX-RS 的支持,并提供了更强大的 Spring MVC RESTful 开发方式,这也是一个非常流行的选择。

安全性、性能与监控

  • 安全性
    • SOAP: 内置 WS-Security 标准,支持 XML 签名、加密等,非常强大。
    • REST: 通常使用标准的 Web 安全机制,如 HTTPS、OAuth 2.0、JWT (JSON Web Tokens)、API Key 等。
  • 性能

    REST 通常比 SOAP 性能更好,因为消息体更小(JSON vs XML),没有额外的 SOAP 信封开销。

  • 监控

    无论哪种风格,都需要对 API 进行监控,可以使用工具如 Prometheus + Grafana, ELK Stack, 或商业 API 网关(如 Kong, Apigee)来跟踪请求量、响应时间、错误率等。

总结与学习资源

Java Web Service 技术已经非常成熟,从最初的 SOAP 到如今主导的 RESTful,核心思想都是让应用之间能够通过网络进行高效、标准化的通信。

  • 学习建议

    1. 打好基础:深入理解 HTTP 协议、XML 和 JSON。
    2. 从 REST 开始:对于大多数现代开发者,掌握 JAX-RS (如 Jersey) 和 RESTful 设计原则是首要任务。
    3. 了解 SOAP:不要完全抛弃 SOAP,了解其原理和适用场景,在企业级项目中你可能会遇到。
    4. 学习框架:深入一个主流框架(如 Jersey 或 Spring Boot),并学习其高级特性(如依赖注入、AOP、过滤器等)。
    5. 实践项目:通过动手实践来巩固知识,比如构建一个完整的 CRUD API。
  • 学习资源

希望这份详尽的教程能帮助你顺利入门并掌握 Java Web Service 开发!

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