杰瑞科技汇

Java webservice教程怎么学?入门到实战指南?

Java WebService 完整教程

目录

  1. 第一部分:核心概念
    • 什么是 WebService?
    • 为什么需要 WebService?
    • WebService 的核心标准(SOAP, WSDL, UDDI)
  2. 第二部分:主流技术栈
    • JAX-WS (Java API for XML Web Services)
    • JAX-RS (Java API for RESTful Web Services)
  3. 第三部分:实战 - 使用 JAX-WS 开发传统 WebService
    • 环境准备
    • 开发步骤(服务端)
    • 开发步骤(客户端)
    • 运行与测试
  4. 第四部分:实战 - 使用 JAX-RS 开发 RESTful WebService
    • 什么是 REST?
    • 环境准备(引入 Jersey 框架)
    • 开发步骤(服务端)
    • 运行与测试(使用 Postman)
  5. 第五部分:技术选型与总结
    • JAX-WS vs. JAX-RS
    • 总结与学习路径

第一部分:核心概念

什么是 WebService?

WebService 是一种跨编程语言、跨操作系统的远程调用技术,它允许不同的应用程序通过网络进行交互,就像调用本地方法一样调用远程服务器上的方法。

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

你可以把它想象成:

一个应用程序在互联网上暴露了一个“服务端点”,其他任何应用程序都可以通过标准的 HTTP 协议来访问这个端点,并请求执行某个功能,然后得到返回结果。

为什么需要 WebService?

  • 系统集成:将不同技术栈(如 Java, .NET, Python)构建的系统无缝集成。
  • 跨平台通信:解决了不同操作系统之间数据交换的难题。
  • 复用现有功能:可以将核心业务逻辑封装成 WebService,供多个客户端复用。
  • B2B 交互:企业之间通过标准化的接口进行数据交换(如订单、物流信息)。

WebService 的核心标准

  • SOAP (Simple Object Access Protocol)

    • 是什么:一种基于 XML 的协议,用于在 Web 上交换结构化信息。
    • 特点
      • 协议独立(通常基于 HTTP)。
      • 格式严格,是自描述的 XML。
      • 包含三个部分:Envelope(信封,必须)、Header(头部,可选)、Body(正文,必须)。
      • 因为 XML 格式冗长,解析复杂,性能相对较低,但安全性和可靠性高。
  • WSDL (Web Services Description Language)

    Java webservice教程怎么学?入门到实战指南?-图2
    (图片来源网络,侵删)
    • 是什么:一个基于 XML 的语言,用于描述 WebService 的功能。
    • 作用:可以理解为 WebService 的“说明书”或“接口文档”,它告诉客户端:
      • 服务的地址在哪里?
      • 服务提供了哪些方法(操作)?
      • 每个方法的输入参数是什么?
      • 每个方法的返回值是什么?
      • 通信需要使用什么协议(如 SOAP/HTTP)?
    • 客户端通过读取 WSDL 文件,就能知道如何调用这个服务。
  • UDDI (Universal Description, Discovery, and Integration)

    • 是什么:一个基于 XML 的注册中心,用于发布和发现 WebService。
    • 作用:你可以把它想象成“WebService 的黄页”,企业可以将自己的 WebService 发布到 UDDI 注册中心,其他企业则可以在这里搜索到自己需要的服务。
    • 现状:由于安全和商业模式等原因,UDDI 并未像预期那样普及,现在更多的是通过直接提供 WSDL 地址或 API 文档来发现服务。

第二部分:主流技术栈

Java 官方提供了两套 API 来开发 WebService,分别对应 SOAP 和 REST 风格。

JAX-WS (Java API for XML Web Services)

  • 目标:用于创建和消费 SOAP 风格的 WebService。
  • 特点
    • 是 Java EE 的标准组成部分,无需额外引入核心 API。
    • 提供了丰富的注解(如 @WebService, @WebMethod)来快速开发。
    • 能够自动生成 WSDL 文件。
    • 在 Java 6 之后,JDK 自带了 wsimport 工具,可以方便地根据 WSDL 生成客户端代码。
  • 实现框架:JDK 内置的实现(Metro)是主流。

JAX-RS (Java API for RESTful Web Services)

  • 目标:用于创建和消费 REST 风格的 WebService。
  • 特点
    • 更轻量级,基于 HTTP 协议,通常使用 JSON 或 XML 作为数据交换格式。
    • 开发简单,性能高,是目前 Web 和移动端 API 开发的首选。
    • 使用 HTTP 动词(GET, POST, PUT, DELETE)来操作资源。
    • 使用 URL 来定位资源(如 /users/123)。
  • 实现框架:JAX-RS 只是一个规范,需要第三方框架来实现,最流行的实现是 JerseyRESTEasy

第三部分:实战 - 使用 JAX-WS 开发传统 WebService

我们将创建一个简单的计算器服务,提供加法和减法功能。

环境准备

  • JDK 8 或更高版本。
  • 一个 IDE(如 IntelliJ IDEA 或 Eclipse)。
  • 一个 Web 容器(如 Tomcat 9.x),JDK 自带的 Endpoint 可以用于快速测试,但部署到 Web 容器是更标准的做法。

开发步骤(服务端)

  1. 创建 Maven Web 项目 在你的 IDE 中创建一个名为 jax-ws-server 的 Maven Web 项目。

    Java webservice教程怎么学?入门到实战指南?-图3
    (图片来源网络,侵删)
  2. 编写服务接口和实现类 JAX-WS 要求服务实现类必须有一个服务接口。

    • com.example.CalculatorService.java (接口)

      import javax.jws.WebMethod;
      import javax.jws.WebService;
      import javax.jws.soap.SOAPBinding;
      // @WebService: 将此接口标记为 WebService 接口
      // @SOAPBinding: 指定 SOAP 绑定风格,默认是 DOCUMENT
      @WebService
      @SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
      public interface CalculatorService {
          // @WebMethod: 将此方法标记为 WebService 的一个操作
          @WebMethod
          int add(int a, int b);
          @WebMethod
          int subtract(int a, int b);
      }
    • com.example.CalculatorServiceImpl.java (实现类)

      import javax.jws.WebService;
      // @WebService: 指定此实现类实现了哪个服务接口
      // endpointInterface 属性是必须的,它连接了接口和实现
      @WebService(endpointInterface = "com.example.CalculatorService")
      public class CalculatorServiceImpl implements CalculatorService {
          @Override
          public int add(int a, int b) {
              System.out.println("WebService add method called with a=" + a + ", b=" + b);
              return a + b;
          }
          @Override
          public int subtract(int a, int b) {
              System.out.println("WebService subtract method called with a=" + a + ", b=" + b);
              return a - b;
          }
      }
  3. 发布 WebService 你可以通过两种方式发布服务:

    • 使用 JDK 内置的 Endpoint(适合快速测试) 创建一个主类 com.example.Publisher

      import javax.xml.ws.Endpoint;
      public class Publisher {
          public static void main(String[] args) {
              // 创建服务的实现实例
              CalculatorService calculatorService = new CalculatorServiceImpl();
              // 发布服务
              // 第一个参数是服务的访问地址
              // 第二个参数是服务的实现对象
              Endpoint.publish("http://localhost:8080/calculator", calculatorService);
              System.out.println("WebService is published successfully at http://localhost:8080/calculator?wsdl");
          }
      }

      运行 Publisher 类,然后访问 http://localhost:8080/calculator?wsdl,如果能看到一个 XML 文件(WSDL),说明发布成功。

    • 部署到 Web 容器(如 Tomcat,标准做法)

      • 配置 web.xml: 在 src/main/webapp/WEB-INF/web.xml 中添加:
        <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
                 version="4.0">
            <listener>
                <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
            </listener>
            <servlet>
                <servlet-name>CalculatorService</servlet-name>
                <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
            </servlet>
            <servlet-mapping>
                <servlet-name>CalculatorService</servlet-name>
                <url-pattern>/calculator</url-pattern>
            </servlet-mapping>
        </web-app>
      • 创建 sun-jaxws.xml: 在 src/main/webapp/WEB-INF/ 目录下创建 sun-jaxws.xml 文件:
        <endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
            <endpoint
                    name="CalculatorService"
                    implementation="com.example.CalculatorServiceImpl"
                    url-pattern="/calculator"/>
        </endpoints>
      • 打包并部署:将项目打包成 WAR 文件,然后部署到 Tomcat,启动 Tomcat 后,访问 http://your-tomcat-host:8080/your-project-name/calculator?wsdl 即可看到 WSDL。

开发步骤(客户端)

使用 wsimport 工具可以自动生成客户端代码。

  1. 打开命令行,进入你的项目目录。

  2. 执行 wsimport 命令

    # -p: 指定生成的客户端代码包名
    # -d: 指定生成.class文件的存放目录
    # -keep: 保留生成的源文件
    wsimport -p com.example.client -d target/generated-sources -keep http://localhost:8080/calculator?wsdl

    执行后,会在 target/generated-sources 目录下生成一堆客户端代码(包括接口、实现类、辅助类等)。

  3. 编写客户端调用代码src/main/java 下创建客户端类 com.example.ClientTest

    import com.example.client.CalculatorService;
    import com.example.client.CalculatorServiceImplService;
    public class ClientTest {
        public static void main(String[] args) {
            // 通过 WSDL 中的服务名称(<service name="...">)来创建服务实例
            CalculatorServiceImplService service = new CalculatorServiceImplService();
            // 从服务实例中获取服务端口(即接口)
            CalculatorService calculatorPort = service.getCalculatorServiceImplPort();
            // 像调用本地方法一样调用远程方法
            int resultAdd = calculatorPort.add(10, 5);
            System.out.println("10 + 5 = " + resultAdd);
            int resultSubtract = calculatorPort.subtract(10, 5);
            System.out.println("10 - 5 = " + resultSubtract);
        }
    }

    运行 ClientTest,如果控制台输出了正确的结果,说明客户端调用成功。


第四部分:实战 - 使用 JAX-RS 开发 RESTful WebService

我们将创建一个用户管理服务,提供查询用户列表和根据 ID 查询用户的功能。

环境准备

  • JDK 8+
  • IDE
  • Maven
  • Jersey 框架依赖:Jersey 是 JAX-RS 的一个流行实现。

开发步骤(服务端)

  1. 创建 Maven 项目 创建一个名为 jax-rs-server 的 Maven 项目。

  2. 添加 Jersey 依赖pom.xml 中添加:

    <dependencies>
        <!-- Jersey 核心依赖 -->
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.39</version>
        </dependency>
        <!-- 支持 JSON 格式 -->
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-binding</artifactId>
            <version>2.39</version>
        </dependency>
        <!-- 为了简化日志,可以加入一个日志实现,如 Logback 或 Log4j2 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.7</version>
        </dependency>
    </dependencies>
  3. 配置 Web 容器(Servlet 3.0+) 创建 src/main/java/com/example/MyApplication.java,这是 Jersey 的应用入口。

    import org.glassfish.jersey.server.ResourceConfig;
    import org.glassfish.jersey.servlet.ServletContainer;
    import org.glassfish.jersey.servlet.ServletProperties;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import java.util.HashSet;
    import java.util.Set;
    // 自定义的 HttpServlet,用于启动 Jersey
    public class MyApplication extends HttpServlet {
        @Override
        public void init(ServletConfig config) throws ServletException {
            super.init(config);
            ResourceConfig resourceConfig = new ResourceConfig();
            // 注册资源类
            resourceConfig.packages("com.example.resource");
            // 设置 Servlet 属性
            config.getServletContext().setAttribute(
                    ServletProperties.JAXRS_APPLICATION_CLASS,
                    resourceConfig.getClass().getName());
        }
    }

    src/main/webapp/WEB-INF/web.xml 中配置 Servlet 映射:

    <web-app>
        <servlet>
            <servlet-name>Jersey Web Application</servlet-name>
            <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
            <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>

    注意:如果你使用的是较新的 Tomcat 版本(支持 Servlet 3.0+),可以使用无 web.xml 的方式,通过 @ApplicationPath 注解来配置。

  4. 创建资源类src/main/java/com/example/resource 包下创建 UserResource.java

    import javax.ws.rs.*;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import java.util.*;
    @Path("/users") // 定义资源的基本路径
    public class UserResource {
        // 模拟一个数据库
        private static final Map<Long, User> userDB = new HashMap<>();
        static {
            userDB.put(1L, new User(1, "Alice"));
            userDB.put(2L, new User(2, "Bob"));
        }
        // @GET: 表示这是一个 HTTP GET 请求
        // @Produces: 指定返回的媒体类型,这里是 JSON
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        public List<User> getAllUsers() {
            System.out.println("GET /users called");
            return new ArrayList<>(userDB.values());
        }
        // @Path: 在类路径的基础上再添加子路径
        // @PathParam: 从 URL 路径中获取参数
        // @GET: 同样是 GET 请求
        @GET
        @Path("/{id}")
        @Produces(MediaType.APPLICATION_JSON)
        public Response getUserById(@PathParam("id") long id) {
            System.out.println("GET /users/" + id + " called");
            User user = userDB.get(id);
            if (user == null) {
                // 如果用户不存在,返回 404 Not Found
                return Response.status(Response.Status.NOT_FOUND).entity("User not found").build();
            }
            // 如果用户存在,返回 200 OK 和用户数据
            return Response.ok(user).build();
        }
        // 一个简单的 User 类
        public static class User {
            private long id;
            private String name;
            public User() {}
            public User(long id, String name) {
                this.id = id;
                this.name = name;
            }
            // Getters and Setters (必须要有,否则 JSON 序列化会失败)
            public long getId() { return id; }
            public void setId(long id) { this.id = id; }
            public String getName() { return name; }
            public void setName(String name) { this.name = name; }
            @Override
            public String toString() {
                return "User{" + "id=" + id + ", name='" + name + '\'' + '}';
            }
        }
    }
  5. 部署和测试 将项目打包成 WAR 并部署到 Tomcat,启动 Tomcat。

运行与测试(使用 Postman 或浏览器)

  • 获取所有用户:

    • 方法: GET
    • URL: http://localhost:8080/your-project-name/api/users
    • 预期响应 (200 OK):
      [
        {
          "id": 1,
          "name": "Alice"
        },
        {
          "id": 2,
          "name": "Bob"
        }
      ]
  • 获取 ID 为 1 的用户:

    • 方法: GET
    • URL: http://localhost:8080/your-project-name/api/users/1
    • 预期响应 (200 OK):
      {
        "id": 1,
        "name": "Alice"
      }
  • 获取 ID 为 999 的用户(不存在):

    • 方法: GET
    • URL: http://localhost:8080/your-project-name/api/users/999
    • 预期响应 (404 Not Found):
      User not found

第五部分:技术选型与总结

JAX-WS vs. JAX-RS

特性 JAX-WS (SOAP) JAX-RS (REST)
协议 基于 XML 的 SOAP 协议 基于 HTTP 协议
数据格式 严格、冗长的 XML 轻量级的 JSON, XML, Text 等
风格 面向操作/方法 面向资源
地址 http://host/service?wsdl http://host/resource/id
HTTP 动词 不直接使用 使用 (GET, POST, PUT, DELETE)
缓存 不支持 支持 (利用 HTTP 缓存机制)
性能 较低 (XML 解析开销大) 较高 (JSON 解析快,无额外协议开销)
安全性 内置 WS-Security 标准 通常依赖 HTTPS 和 OAuth2 等标准
适用场景 企业级应用集成(B2B)、银行、金融等对安全性和事务性要求高的场景 公开 API、Web 应用、移动后端、微服务

总结与学习路径

  • 入门建议:直接从 JAX-RS (REST) 开始,因为它是目前业界的主流,更简单、更灵活、性能更好,掌握 RESTful API 设计是现代开发者的必备技能。
  • 何时学习 JAX-WS:如果你需要维护遗留的 SOAP 系统,或者在某些特定行业(如金融、电信)的集成项目中,SOAP 仍然是强制要求时,才需要深入学习 JAX-WS。
  • 学习路径
    1. 掌握基础:理解 HTTP 协议(GET, POST, PUT, DELETE, 状态码)。
    2. 学习 REST 设计原则:理解资源、URI、无状态等概念。
    3. 精通 JAX-RS (Jersey):熟练使用 @Path, @GET, @POST, @Produces, @Consumes, @PathParam, @QueryParam 等核心注解。
    4. 进阶学习:学习依赖注入(DI)、异常处理、过滤器、拦截器、以及如何与数据库(如 JPA)结合。
    5. 了解 JAX-WS:了解其基本概念和工作原理,知道如何开发和调用一个简单的 SOAP 服务即可。

希望这份详尽的教程能对你有所帮助!祝你学习愉快!

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