杰瑞科技汇

java开发webservice

Java 开发 WebService 主要有两种主流技术栈:

  1. JAX-WS (Java API for XML Web Services):这是 Java 官方、标准的 WebService 开发技术,它比较成熟,广泛应用于传统的 Java EE(Jakarta EE)项目中,对于简单的 POJO(普通 Java 对象)非常友好,可以快速上手。
  2. JAX-RS (Java API for RESTful Web Services):这是用于开发 RESTful 风格 WebService 的 API,随着移动互联网和前后端分离架构的流行,RESTful API 已成为主流,JAX-RS 通常与 JSON 数据格式配合使用,更轻量、更灵活。

下面我将分别对这两种技术进行详细的讲解,并提供完整的开发示例。


第一部分:使用 JAX-WS 开发传统 WebService

JAX-WS 的核心思想是,你只需要编写一个普通的 Java 接口和它的实现类,然后通过一些注解,JAX-WS 框架就能帮你自动将它们转换成可以通过 SOAP 协议访问的 WebService。

核心概念和注解

  • @WebService: 用于在接口或实现类上,标记它是一个 WebService。
    • 在接口上使用,表示这是一个服务端点接口。
    • 在实现类上使用,表示这是一个服务端点实现。
  • @WebMethod: 用于在接口的方法上,标记这个方法是一个可以被远程调用的 WebService 操作,如果不加,默认所有 public 方法都会被暴露。
  • @WebParam: 用于在方法的参数上,指定参数的名称(在 WSDL 文件中会体现)。
  • @WebResult: 用于在方法的返回值上,指定返回值的名称。

开发步骤(以原生 JAX-WS 为例)

环境准备: 你需要 JDK 1.6 或更高版本,因为 JAX-WS 已经被集成到了 JDK 中。

示例:创建一个简单的计算器 WebService

创建服务端点接口

// src/com/example/Calculator.java
package com.example;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// @WebService: 标记这是一个WebService接口
// name: 指定WebService的名称
// targetNamespace: 指定命名空间,通常是接口包名的反序
// @SOAPBinding: 指定SOAP消息的风格,默认是 DOCUMENT
@WebService(name = "Calculator", targetNamespace = "http://example.com/")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
public interface Calculator {
    // @WebMethod: 标记这是一个可以被远程调用的方法
    // @WebParam: 指定参数名
    // @WebResult: 指定返回值名
    @WebMethod
    @WebResult(name = "sumResult")
    public int add(
            @WebParam(name = "a") int a,
            @WebParam(name = "b") int b);
    @WebMethod
    @WebResult(name = "diffResult")
    public int subtract(
            @WebParam(name = "a") int a,
            @WebParam(name = "b") int b);
}

创建服务端点实现类

// src/com/example/CalculatorImpl.java
package com.example;
import javax.jws.WebService;
// @WebService: 标记这是一个WebService的实现类
// endpointInterface: 指定它实现了哪个接口
@WebService(endpointInterface = "com.example.Calculator")
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
    @Override
    public int subtract(int a, int b) {
        return a - b;
    }
}

发布 WebService

你需要一个主类来启动一个内嵌的 HTTP 服务器,并将你的实现类发布出去。

// src/com/example/CalculatorPublisher.java
package com.example;
import javax.xml.ws.Endpoint;
// Endpoint 是 JAX-WS 提供的用于发布 WebService 的工具类
public class CalculatorPublisher {
    public static void main(String[] args) {
        // 定义WebService的发布地址
        String address = "http://localhost:8888/calculator";
        // 发布WebService
        // 第一个参数是访问地址,第二个参数是WebService的实现类实例
        Endpoint.publish(address, new CalculatorImpl());
        System.out.println("WebService is published at: " + address);
    }
}

运行和测试

  1. 运行:直接运行 CalculatorPublishermain 方法。
  2. 验证 WSDL:在浏览器中访问 http://localhost:8888/calculator?wsdl,如果能看到一堆 XML 内容,说明你的 WebService 发布成功了,这就是 WSDL (Web Services Description Language) 文件,它描述了如何调用你的服务。

创建客户端调用

JDK 提供了 wsimport 工具,可以根据 WSDL 文件自动生成客户端调用代码。

  1. 生成客户端代码: 打开命令行,进入你的项目目录(或者任意目录),执行以下命令:

    wsimport -keep -p com.example.client http://localhost:8888/calculator?wsdl
    • -keep: 生成源代码。
    • -p com.example.client: 指定生成代码的包名。
    • 后面是 WSDL 文件的地址。
  2. 使用生成的客户端代码wsimport 会生成一堆文件,最重要的是 CalculatorCalculatorService 这两个类。 你可以写一个测试类来调用服务:

    // src/com/example/client/CalculatorClient.java
    package com.example.client;
    public class CalculatorClient {
        public static void main(String[] args) {
            // 创建服务实例,通过wsdlLocation指定wsdl地址
            CalculatorService service = new CalculatorService();
            // 获取服务端点,portName需要从生成的wsdl文件中查看<port name="CalculatorPort">...</port>
            Calculator calculator = service.getCalculatorPort();
            // 调用远程方法
            int sum = calculator.add(10, 20);
            System.out.println("10 + 20 = " + sum);
            int diff = calculator.subtract(50, 25);
            System.out.println("50 - 25 = " + diff);
        }
    }

    运行 CalculatorClient,你将看到控制台输出正确的结果。


第二部分:使用 JAX-RS 开发 RESTful WebService

RESTful WebService 更符合现代 Web 应用的设计理念,它使用标准的 HTTP 方法(GET, POST, PUT, DELETE)来操作资源,数据格式通常是轻量级的 JSON 或 XML。

核心概念和注解

  • @Path: 用于类或方法上,定义 URL 的路径。
  • @GET, @POST, @PUT, @DELETE: 用于方法上,定义 HTTP 请求方法。 *. @Produces: 用于方法上,定义该方法能返回的媒体类型(如 application/json, application/xml)。
  • @Consumes: 用于方法上,定义该方法能接受的请求体媒体类型。 *. @QueryParam: 用于获取 URL 中的查询参数(?key=value)。
  • @PathParam: 用于获取 URL 路径中的参数(/users/{id})。
  • @FormParam: 用于获取表单提交的参数。
  • @BeanParam: 用于将多个参数封装到一个对象中。

开发步骤(以 Jersey 框架为例)

虽然 JAX-RS 是 Java 标准,但你需要一个实现框架,最流行的实现是 JerseyRESTEasy,这里我们以 Jersey 为例。

环境准备: 你需要一个构建工具(如 Maven 或 Gradle)来管理 Jersey 的依赖。

Maven 依赖 (pom.xml)

<dependencies>
    <!-- Jersey 核心依赖 -->
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-grizzly2-http</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>
    <!-- Lombok (可选,简化代码) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

示例:创建一个用户管理 RESTful API

创建一个实体类

// src/com/example/model/User.java
package com.example.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data // Lombok: 自动生成 getter, setter, toString 等
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private String email;
}

创建资源类

这是 JAX-RS 的核心,相当于 JAX-WS 中的 SEI 和 SEI 实现的结合体。

// src/com/example/resource/UserResource.java
package com.example.resource;
import com.example.model.User;
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.Optional;
import java.util.stream.Collectors;
@Path("/users") // 定义基础路径
public class UserResource {
    // 模拟一个数据库
    private List<User> users = new ArrayList<>();
    private int currentId = 1;
    // GET /users - 获取所有用户
    @GET
    @Produces(MediaType.APPLICATION_JSON) // 声明返回 JSON 格式
    public List<User> getAllUsers() {
        return users;
    }
    // GET /users/{id} - 根据 ID 获取单个用户
    @GET
    @Path("/{id}") // 定义路径参数
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUserById(@PathParam("id") int id) {
        Optional<User> userOptional = users.stream()
                .filter(u -> u.getId() == id)
                .findFirst();
        if (userOptional.isPresent()) {
            return Response.ok(userOptional.get()).build(); // 200 OK
        } else {
            return Response.status(Response.Status.NOT_FOUND).build(); // 404 Not Found
        }
    }
    // POST /users - 创建一个新用户
    @POST
    @Consumes(MediaType.APPLICATION_JSON) // 声明接收 JSON 格式的请求体
    @Produces(MediaType.APPLICATION_JSON)
    public Response createUser(User user) {
        user.setId(currentId++);
        users.add(user);
        // 返回 201 Created,并在 Location 头中给出新资源的 URI
        return Response.status(Response.Status.CREATED)
                .entity(user)
                .build();
    }
    // PUT /users/{id} - 更新一个用户
    @PUT
    @Path("/{id}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response updateUser(@PathParam("id") int id, User updatedUser) {
        for (int i = 0; i < users.size(); i++) {
            User user = users.get(i);
            if (user.getId() == id) {
                updatedUser.setId(id); // 确保ID不被修改
                users.set(i, updatedUser);
                return Response.ok(updatedUser).build(); // 200 OK
            }
        }
        return Response.status(Response.Status.NOT_FOUND).build(); // 404 Not Found
    }
    // DELETE /users/{id} - 删除一个用户
    @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(); // 404 Not Found
        }
    }
}

创建应用程序启动类

// src/com/example/MyApplication.java
package com.example;
import com.example.resource.UserResource;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.grizzly.http.server.HttpServer;
public class MyApplication {
    public static void main(String[] args) {
        // 创建 ResourceConfig 并注册我们的资源类
        ResourceConfig resourceConfig = new ResourceConfig(UserResource.class);
        // 创建并启动 HTTP 服务器
        HttpServer server = org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory
                .createHttpServer(java.net.URI.create("http://localhost:8080/"), resourceConfig);
        System.out.println("Server started at http://localhost:8080/");
        try {
            server.start();
            // 保持服务器运行
            Thread.currentThread().join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行和测试

  1. 运行:直接运行 MyApplicationmain 方法。

  2. 测试:你可以使用 Postman、curl 或浏览器来测试这些 API。

    • 创建用户 (POST):
      curl -X POST -H "Content-Type: application/json" -d '{"name":"Alice","email":"alice@example.com"}' http://localhost:8080/users
    • 获取所有用户 (GET):
      curl http://localhost:8080/users
    • 获取单个用户 (GET):
      curl http://localhost:8080/users/1
    • 更新用户 (PUT):
      curl -X PUT -H "Content-Type: application/json" -d '{"name":"Alice Smith","email":"alice.smith@example.com"}' http://localhost:8080/users/1
    • 删除用户 (DELETE):
      curl -X DELETE http://localhost:8080/users/1

总结与对比

特性 JAX-WS (SOAP) JAX-RS (REST)
协议 强制使用 SOAP 协议(基于 XML) 使用标准 HTTP/HTTPS 协议
数据格式 主要是 XML 主要是 JSON,也支持 XML 等
风格 面向操作,有严格的契约(WSDL) 面向资源,更灵活,无状态
地址空间 动态地址,通常需要 WSDL 发现 静态、可预测的 URL 地址
标准化 Java EE 标准的一部分 Java EE 标准的一部分
适用场景 企业级应用集成(B2B)、需要高安全性、事务支持的场景 Web 应用、移动应用后端、前后端分离项目
学习曲线 相对较陡,概念较多(WSDL, SOAP, Binding 等) 相对平缓,更贴近 Web 开发者习惯

如何选择?

  • 如果你的项目是传统的企业内部系统,需要和遗留系统集成,或者对安全性、事务性有非常高的要求,可以考虑 JAX-WS
  • 如果你在开发新的 Web 应用、移动 App 后端 API,或者采用前后端分离架构,JAX-RS 是不二之选,它是目前业界的主流,更轻量、更易于理解和维护。

在现代 Spring Boot 框架中,开发 RESTful API 通常会直接使用 Spring MVC 的 @RestController,其设计理念与 JAX-RS 非常相似,但配置更简单,生态更强大,但对于理解 Java 原生 WebService JAX-WS 和 JAX-RS 仍然是重要的基础。

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