杰瑞科技汇

Java如何搭建WebService?

  1. JAX-WS (Java API for XML Web Services):这是 Java 标准的 WebService 技术,非常成熟、稳定,广泛用于企业级应用,它通常使用 SOAP (Simple Object Access Protocol) 协议进行通信。
  2. JAX-RS (Java API for RESTful Web Services):这是用于构建 RESTful 风格 Web 服务的 Java API,它更轻量级,通常基于 HTTP 协议,使用 JSON 或 XML 作为数据格式,是目前 Web 开发的主流方式。

下面我将分别详细介绍如何使用这两种技术来搭建 WebService。

Java如何搭建WebService?-图1
(图片来源网络,侵删)

使用 JAX-WS (SOAP WebService)

JAX-WS 是 Java EE 的一部分,所以如果你使用的是像 Tomcat 这样的 Web 服务器,你需要引入额外的库(如 jaxws-rt),如果使用像 JBoss/WildFly 这样的应用服务器,则通常已经内置了支持。

这里我们以最常用的方式:使用 JDK 内置的 wsimport 工具生成客户端,并手动编写服务端为例。

环境准备

  • JDK 8 或更高版本
  • 一个 Web 服务器,如 Apache Tomcat (9.x)
  • 一个 IDE,如 IntelliJ IDEA 或 Eclipse

服务端开发

步骤 1:创建 Maven Web 项目

在 IDEA 或 Eclipse 中创建一个新的 Maven Web 项目。

Java如何搭建WebService?-图2
(图片来源网络,侵删)

步骤 2:添加依赖

pom.xml 文件中添加 JAX-WS 的运行时库。jaxws-rt 是一个非常流行的实现,它可以在 Tomcat 等非 Java EE 容器中运行。

<dependencies>
    <!-- JAX-WS RI (Reference Implementation) -->
    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>2.3.3</version>
    </dependency>
</dependencies>

步骤 3:编写服务接口 (SEI - Service Endpoint Interface)

这个接口定义了 WebService 提供的方法,它必须使用 @WebService 注解。

Java如何搭建WebService?-图3
(图片来源网络,侵删)
// src/main/java/com/example/service/UserService.java
package com.example.service;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
@WebService
public interface UserService {
    /**
     * 根据用户ID获取用户信息
     * @param userId 用户ID
     * @return 用户信息字符串
     */
    @WebMethod
    String getUserInfo(@WebParam(name = "userId") String userId);
    /**
     * 欢迎方法
     * @param name 用户名
     * @return 欢迎字符串
     */
    @WebMethod
    String sayHello(@WebParam(name = "name") String name);
}

步骤 4:编写服务实现类 (SIB - Service Implementation Bean)

这个类实现了上面定义的接口。

// src/main/java/com/example/service/UserServiceImpl.java
package com.example.service;
import javax.jws.WebService;
@WebService(endpointInterface = "com.example.service.UserService")
public class UserServiceImpl implements UserService {
    @Override
    public String getUserInfo(String userId) {
        // 模拟业务逻辑
        if ("001".equals(userId)) {
            return "User ID: 001, Name: Zhang San, Email: zhangsan@example.com";
        } else {
            return "User not found.";
        }
    }
    @Override
    public String sayHello(String name) {
        return "Hello, " + name + "!";
    }
}

步骤 5:发布 WebService

你需要一个类来启动并发布这个服务,这个类通常会在 Web 应用启动时被调用。

// src/main/java/com/example/publisher/WebServicePublisher.java
package com.example.publisher;
import com.example.service.UserServiceImpl;
import javax.xml.ws.Endpoint;
public class WebServicePublisher {
    public static void main(String[] args) {
        // 定义WebService的发布地址
        String address = "http://localhost:8080/myapp/userService";
        // 创建服务实现类实例
        UserServiceImpl userServiceImpl = new UserServiceImpl();
        // 发布WebService
        Endpoint.publish(address, userServiceImpl);
        System.out.println("WebService is published at: " + address);
    }
}

注意Endpoint.publish() 这种方式主要用于开发和测试,在生产环境中,通常会将 WebService 部署到 Servlet 容器中,通过 web.xml 进行配置。

步骤 6:部署和测试

  1. 运行发布类:直接运行 WebServicePublishermain 方法。

  2. 访问 WSDL:打开浏览器,访问 http://localhost:8080/myapp/userService?wsdl,如果看到一个 XML 文件,说明服务发布成功,这个 WSDL 文件是客户端用来调用服务的“说明书”。

  3. 测试客户端:可以使用 wsimport 命令行工具生成客户端代码进行测试。

    # 在命令行执行,-p 指定包名,-keep 保留生成的文件
    wsimport -p com.example.client -keep http://localhost:8080/myapp/userService?wsdl

    执行后,会在 com.example.client 包下生成一堆 Java 文件(如 UserServiceUserService_Service 等),然后你可以编写一个简单的 Java 客户端来调用:

    // 客户端调用代码
    import com.example.client.UserService;
    import com.example.client.UserService_Service;
    public class JaxWsClientTest {
        public static void main(String[] args) {
            // 创建服务视图
            UserService_Service service = new UserService_Service();
            // 获取服务端口
            UserService userService = service.getUserServicePort();
            // 调用远程方法
            String helloResult = userService.sayHello("World");
            System.out.println(helloResult);
            String userInfoResult = userService.getUserInfo("001");
            System.out.println(userInfoResult);
        }
    }

使用 JAX-RS (RESTful WebService)

JAX-RS 的标准实现是 JerseyRESTEasy,这里我们以 Jersey 为例,因为它也是由 Oracle (Sun) 官方提供的参考实现。

环境准备

  • JDK 8 或更高版本
  • 一个 Web 服务器,如 Apache Tomcat (9.x)
  • 一个 IDE,如 IntelliJ IDEA 或 Eclipse

服务端开发

步骤 1:创建 Maven Web 项目

步骤 2:添加依赖

pom.xml 中添加 Jersey 的核心依赖。

<dependencies>
    <!-- Jersey 2.x 核心依赖 -->
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.35</version>
    </dependency>
    <!-- 支持 JSON -->
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.35</version>
    </dependency>
</dependencies>

步骤 3:配置 web.xml

告诉 Servlet 容器如何初始化 Jersey。

<!-- 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">
    <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.resource</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>

步骤 4:创建资源类 (Resource Class)

这是 JAX-RS 的核心,使用注解来映射 HTTP 请求。

// src/main/java/com/example/resource/UserResource.java
package com.example.resource;
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 Map<String, User> userDB = new HashMap<>();
    public UserResource() {
        userDB.put("1", new User("1", "Alice", "alice@example.com"));
        userDB.put("2", new User("2", "Bob", "bob@example.com"));
    }
    // GET /api/users/1
    @GET
    @Path("/{userId}")
    @Produces(MediaType.APPLICATION_JSON) // 指定返回格式为 JSON
    public Response getUserById(@PathParam("userId") String userId) {
        User user = userDB.get(userId);
        if (user == null) {
            return Response.status(Response.Status.NOT_FOUND).entity("User not found").build();
        }
        return Response.ok(user).build();
    }
    // GET /api/users
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<User> getAllUsers() {
        return new ArrayList<>(userDB.values());
    }
    // POST /api/users
    @POST
    @Consumes(MediaType.APPLICATION_JSON) // 指定接收格式为 JSON
    @Produces(MediaType.APPLICATION_JSON)
    public Response createUser(User user) {
        userDB.put(user.getId(), user);
        return Response.status(Response.Status.CREATED).entity(user).build();
    }
}
// 一个简单的 POJO 类
class User {
    private String id;
    private String name;
    private String email;
    // 构造器、getters 和 setters 是必须的
    public User() {}
    public User(String id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
    // Getters and Setters
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

步骤 5:部署和测试

  1. 将项目打包成 .war 文件并部署到 Tomcat。

  2. 启动 Tomcat。

  3. 使用 API 测试工具(如 Postman, curl 或浏览器)进行测试。

    • 获取所有用户: GET http://localhost:8080/myapp/api/users 预期响应:

      [
        {"id":"1","name":"Alice","email":"alice@example.com"},
        {"id":"2","name":"Bob","email":"bob@example.com"}
      ]
    • 获取单个用户: GET http://localhost:8080/myapp/api/users/1 预期响应:

      {"id":"1","name":"Alice","email":"alice@example.com"}
    • 创建新用户: POST http://localhost:8080/myapp/api/users 请求体 (Body):

      {
        "id": "3",
        "name": "Charlie",
        "email": "charlie@example.com"
      }

      预期响应:

      {"id":"3","name":"Charlie","email":"charlie@example.com"}

总结与对比

特性 JAX-WS (SOAP) JAX-RS (REST)
协议 SOAP (基于 XML,有严格标准) HTTP (GET, POST, PUT, DELETE 等)
数据格式 主要是 XML 主要是 JSON,也支持 XML
风格 面向接口,契约优先 面向资源,无状态
复杂度 较高,配置繁琐 较低,简单直观
性能 较低,SOAP 头部开销大 较高,轻量级
适用场景 企业级应用,需要高安全性、事务支持、ACID 合规的场景 Web 和移动应用 API,前后端分离架构
工具支持 WSDL 自动生成客户端/服务端代码 通常需要手动编写或使用 Swagger 生成文档

如何选择?

  • 如果你的项目是传统的企业应用,需要与 .NET 等其他平台进行复杂的、事务性的交互,并且安全性要求极高,JAX-WS 是一个可靠的选择。
  • 如果你正在构建一个现代化的 Web 应用或移动 App 的后端 API,追求开发效率、性能和前后端分离,JAX-RS (RESTful) 几乎是必然的选择,目前绝大多数新项目都采用 RESTful 风格。
分享:
扫描分享到社交APP
上一篇
下一篇