杰瑞科技汇

Java如何编写WebService?

  1. JAX-WS (Java API for XML Web Services):这是 Java 官方标准,用于构建 SOAP (Simple Object Access Protocol) 风格的 WebService,它非常成熟、稳定,在企业级应用中广泛使用,尤其适合需要高安全性、事务处理和标准化的场景。
  2. JAX-RS (Java API for RESTful Web Services):这是用于构建 REST (Representational State Transfer) 风格 Web 服务的标准,REST 更轻量级、更简单,通常与 JSON 数据格式配合使用,是目前 Web 开发(特别是移动端和前后端分离项目)中最流行的方式。

下面我将分别详细介绍如何使用这两种方式来编写 WebService。

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

使用 JAX-WS (SOAP 风格)

JAX-WS 是 Java EE 的一部分,在标准 JDK 中也包含了其核心实现(javax.xml.ws 包),我们不需要额外引入复杂的框架,只需要使用 JDK 自带的工具即可。

步骤 1:创建一个服务接口

这个接口定义了客户端可以调用的方法,使用 @WebService 注解来标记它。

// src/main/java/com/example/HelloService.java
package com.example;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// @WebService 表示这是一个 WebService 接口
@WebService
// @SOAPBinding(style = SOAPBinding.Style.RPC) 表示使用 RPC 风格,这是默认的
public interface HelloService {
    // @WebMethod 表示这是一个对外暴露的 Web 方法
    // @WebParam 指定参数名,用于 WSDL 文档
    @WebMethod
    String sayHello(@WebParam(name = "name") String name);
}

步骤 2:创建一个服务实现类

这个类实现了上面定义的接口,是 WebService 的具体逻辑。

// src/main/java/com/example/HelloServiceImpl.java
package com.example;
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) {
        System.out.println("WebService 被调用了,参数是: " + name);
        return "你好, " + name + "! 欢迎使用 JAX-WS WebService.";
    }
}

步骤 3:发布 WebService

你可以编写一个主类来发布这个服务,最简单的方式是使用 Endpoint 类。

Java如何编写WebService?-图2
(图片来源网络,侵删)
// 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:8888/ws/hello";
        // 创建服务实现类的实例
        HelloService helloService = new HelloServiceImpl();
        // 发布服务
        // 第一个参数是访问地址,第二个参数是服务的实现实例
        Endpoint.publish(address, helloService);
        System.out.println("WebService 发布成功!");
        System.out.println("访问地址: " + address);
        System.out.println("WSDL 地址: " + address + "?wsdl");
    }
}

步骤 4:运行和测试

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

  2. 验证 WSDL:在浏览器中访问 http://localhost:8888/ws/hello?wsdl,如果看到一个 XML 文件(WSDL 描述文件),说明服务发布成功。

  3. 测试:可以使用专门的 SOAP 客户端工具(如 SoapUI)进行测试,也可以使用 JDK 自带的 wsimport 工具生成客户端代码进行调用。

    使用 wsimport 生成客户端: 打开一个新的命令行窗口(不要关闭发布服务的窗口),执行以下命令:

    # -p: 客户端代码包名
    # -keep: 保留生成的源文件
    # -d: 指定编译后的 .class 文件存放目录
    wsimport -p com.example.client -keep -d ./client http://localhost:8888/ws/hello?wsdl

    这会在 com/example/client 目录下生成一堆 Java 文件,你可以写一个简单的客户端来调用:

    // Client.java
    import com.example.client.HelloService;
    import com.example.client.HelloService_Service;
    public class Client {
        public static void main(String[] args) {
            // 通过服务名称获取服务实例
            HelloService_Service service = new HelloService_Service();
            // 获取服务端口(即实现类)
            HelloService helloPort = service.getHelloServicePort();
            // 调用方法
            String result = helloPort.sayHello("张三");
            System.out.println("客户端收到结果: " + result);
        }
    }

使用 JAX-RS (REST 风格)

JAX-RS 是 Java EE 的一部分,但它的参考实现是 Jersey,另一个非常流行的实现是 RESTEasy,在现代 Java 项目中,我们通常使用 Spring Boot 来集成 JAX-RS(或更常见的 Spring MVC 的 @RestController),因为它极大地简化了配置。

这里我们以 Spring Boot + Jersey 为例,因为它最符合“现代Java写WebService”的实践。

步骤 1:创建 Spring Boot 项目

使用 Spring Initializr 创建一个新项目,并添加以下依赖:

  • Spring Web (虽然我们用 Jersey,但这个依赖通常会有用)
  • Jersey (或 Jersey Spring Web)
  • Spring Boot DevTools (可选,用于热部署)

步骤 2:配置 Jersey

application.propertiesapplication.yml 中配置 Jersey。

# application.properties
# 配置 Jersey servlet 的映射路径
jersey.servlet.application=/api

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

这是 REST 服务的核心,使用 @Path@GET@POST 等注解来定义资源和方法。

// src/main/java/com/example/GreetingResource.java
package com.example;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
// @Component 让 Spring 管理这个 Bean
@Component
// @Path 定义资源的 URI 路径
@Path("/greetings")
public class GreetingResource {
    // @GET 表示这是一个 HTTP GET 请求处理方法
    // @Path 定义该方法在资源下的子路径
    // @Produces 定义该方法返回的媒体类型 (MIME Type)
    @GET
    @Path("/hello")
    @Produces(MediaType.TEXT_PLAIN)
    public String sayHello() {
        return "Hello, Jersey!";
    }
    // @QueryParam 用于获取 URL 中的查询参数
    @GET
    @Path("/greet")
    @Produces(MediaType.APPLICATION_JSON)
    public Greeting greet(@QueryParam("name") String name) {
        // 如果没有提供 name 参数,则使用默认值 "World"
        if (name == null || name.isEmpty()) {
            name = "World";
        }
        return new Greeting("你好, " + name + "!");
    }
    // @POST 表示这是一个 HTTP POST 请求处理方法
    // @Consumes 定义该方法能接受的请求体媒体类型
    @POST
    @Path("/create")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createGreeting(Greeting greeting) {
        // 模拟创建逻辑,比如将问候语存入数据库
        System.out.println("收到一个新的问候语: " + greeting.getMessage());
        // 返回一个响应对象,可以设置状态码、头信息和实体
        greeting.setMessage("已确认: " + greeting.getMessage());
        return Response.status(Response.Status.CREATED).entity(greeting).build();
    }
}
// 一个简单的 POJO,用于 JSON 序列化/反序列化
class Greeting {
    private String message;
    public Greeting() {}
    public Greeting(String message) {
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

步骤 4:配置 Jersey Servlet

创建一个配置类来注册 Jersey。

// src/main/java/com/example/JerseyConfig.java
package com.example;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;
@Component
public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        // 注册这个资源类
        register(GreetingResource.class);
        // 如果需要,可以注册其他特性,如过滤器、异常映射器等
    }
}

步骤 5:运行和测试

  1. 运行:运行 Spring Boot 的主启动类。

  2. 测试:服务启动后,你可以使用 Postman、curl 或浏览器来测试这些 API 端点。

    • GET /api/greetings/hello
      curl http://localhost:8080/api/greetings/hello
      # 响应: Hello, Jersey!
    • GET /api/greetings/greet
      curl "http://localhost:8080/api/greetings/greet?name=李四"
      # 响应 (JSON): {"message":"你好, 李四!"}
    • POST /api/greetings/create
      curl -X POST \
           -H "Content-Type: application/json" \
           -d '{"message":"这是一个测试"}' \
           http://localhost:8080/api/greetings/create
      # 响应 (JSON): {"message":"已确认: 这是一个测试"}

总结与对比

特性 JAX-WS (SOAP) JAX-RS (REST)
协议 SOAP (基于 XML) HTTP (GET, POST, PUT, DELETE 等)
数据格式 主要是 XML,也可以是 JSON 主要是 JSON,也可以是 XML, Text 等
风格 面向服务,有严格的契约 面向资源,轻量级,无状态
标准 Java EE 标准 Java EE 标准
常用实现 JDK 内置 Jersey, RESTEasy
集成框架 可与 Spring 集成,但原生发布简单 与 Spring Boot 集成是主流
优点 - 标准化、强契约
- 内置安全、事务支持
- 自动生成 WSDL 客户端
- 简单、轻量
- 无需额外工具,浏览器和客户端友好
- 与 HTTP 协议紧密结合,利用其所有特性
缺点 - 配置相对复杂
- SOAP 头和消息体较重
- 不适合浏览器直接调用
- 无统一标准,需要自行定义 API 规范
- 缺少内置的标准化安全机制
适用场景 - 企业级应用集成
- 需要高安全性和事务保障的系统
- 金融、电信等传统行业
- 公开 API
- 移动后端服务
- 前后端分离的 Web 应用

如何选择?

  • 如果你正在开发一个需要与 Java EE 生态深度集成、对安全性和事务有严格要求的企业内部系统,或者需要为不同语言的客户端提供一套标准化的、自动生成的调用方式,JAX-WS 是一个不错的选择。
  • 如果你正在开发现代的 Web 应用,特别是需要为移动 App 或前端提供 API 服务,或者你的项目已经基于 Spring BootJAX-RS (通过 Jersey 或 Spring MVC 的 @RestController) 是更简单、更高效的选择,在 Spring 生态中,直接使用 @RestController 是最普遍的做法,其原理和 Jersey 非常相似。
分享:
扫描分享到社交APP
上一篇
下一篇