杰瑞科技汇

Java代码如何生成WSDL文件?

  1. 自上而下(Top-Down):先定义 WSDL 文件,然后根据 WSDL 生成 Java 代码(客户端或服务端骨架),这是更推荐、更标准化的方式,因为它确保了接口的契约先于实现存在。
  2. 自下而上(Bottom-Up):先编写 Java 代码(服务接口和实现),然后由框架(如 JAX-WS)自动生成 WSDL 文件,这种方法在本问答中重点介绍。

下面我将详细讲解第二种方法(自下而上),并提供完整的代码示例。

Java代码如何生成WSDL文件?-图1
(图片来源网络,侵删)

核心概念:JAX-WS

Java API for XML Web Services (JAX-WS) 是 Java 平台用于构建 Web 服务的标准 API,它极大地简化了 Web 服务的开发,当我们使用 JAX-WS 时,WSDL 文件通常不是手动编写的,而是由运行时环境在服务首次部署时自动生成的。

使用 JAX-WS 注解(自下而上)

这是最常见、最直接的方法,你只需要编写标准的 Java 接口和实现类,并使用 JAX-WS 提供的注解来标记 Web 服务,通过一个简单的 Java 程序或构建工具(如 Maven)来触发 WSDL 的生成。

步骤 1:创建 Maven 项目

创建一个标准的 Maven 项目,并添加 JAX-WS 所需的依赖,在 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>java-wsdl-generator</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>jakarta.xml.ws</groupId>
            <artifactId>jakarta.xml.ws-api</artifactId>
            <version>3.0.1</version>
        </dependency>
        <!-- JAX-WS RI (Reference Implementation) - 包含了 wsimport 等工具 -->
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>3.0.2</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- 这个插件可以在编译后自动生成 WSDL 文件到 target 目录 -->
            <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>
                    <sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
                    <wsdlDirectory>${project.build.directory}/wsdl</wsdlDirectory>
                    <!-- 如果需要,可以配置 wsdlLocation -->
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

注意jaxws-maven-pluginwsimport 目标主要是用来从 WSDL 生成客户端代码,为了在编译后直接生成 WSDL,我们通常会用一个简单的 Java 主程序来手动触发生成过程。

Java代码如何生成WSDL文件?-图2
(图片来源网络,侵删)

步骤 2:编写 Web 服务接口

创建一个 Java 接口,并使用 @WebService 注解来标记它。

// src/main/java/com/example/HelloWorld.java
package com.example;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
/**
 * WebService 接口
 */
@WebService(
    name = "HelloWorld", // wsdl:portType 的名称
    serviceName = "HelloWorldService", // wsdl:service 的名称
    targetNamespace = "http://example.com/" // 命名空间,非常重要
)
public interface HelloWorld {
    /**
     * WebService 方法
     * @param name 用户名
     * @return 问候语
     */
    @WebMethod(operationName = "sayHello") // wsdl:operation 的名称
    String sayHello(@WebParam(name = "userName") String name);
}

步骤 3:编写 Web 服务实现类

创建一个实现类,并使用 @WebService 注解(或者 @WebService(endpointInterface = "...") 来明确指定它实现的是哪个接口)。

// src/main/java/com/example/HelloWorldImpl.java
package com.example;
import javax.jws.WebService;
/**
 * WebService 实现类
 */
@WebService(
    endpointInterface = "com.example.HelloWorld" // 指定实现的接口
)
public class HelloWorldImpl implements HelloWorld {
    @Override
    public String sayHello(String name) {
        if (name == null || name.trim().isEmpty()) {
            return "Hello, Stranger!";
        }
        return "Hello, " + name + "!";
    }
}

步骤 4:编写 Java 程序来生成 WSDL

我们写一个主类,利用 JAX-WS 的 Endpoint 类来发布服务,并从发布的服务中获取 WSDL 内容,然后将其写入文件。

// src/main/java/com/example/WsdlGenerator.java
package com.example;
import javax.xml.ws.Endpoint;
import javax.xml.ws.Service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
public class WsdlGenerator {
    public static void main(String[] args) {
        // 1. 定义服务发布的地址(这是一个内存地址,不会被外部访问)
        String address = "http://localhost:8080/ws/hello";
        // 2. 创建并发布服务
        // Endpoint.publish() 会将服务发布到指定的地址,并自动生成 WSDL
        Endpoint endpoint = Endpoint.publish(address, new HelloWorldImpl());
        System.out.println("Service published at: " + address);
        // 3. 从已发布的服务中获取 WSDL 的 URL
        // JAX-WS 规定,WSDL 文件的地址是在服务地址后加上 "?wsdl"
        String wsdlUrl = address + "?wsdl";
        System.out.println("WSDL location: " + wsdlUrl);
        // 4. 创建目标文件
        File wsdlFile = new File("target/hello-world.wsdl");
        // 5. 使用 try-with-resources 确保流被正确关闭
        try (FileOutputStream fos = new FileOutputStream(wsdlFile)) {
            // 6. 从 URL 读取 WSDL 内容并写入文件
            byte[] buffer = new byte[1024];
            int bytesRead;
            URL url = new URL(wsdlUrl);
            while ((bytesRead = url.openStream().read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
            System.out.println("WSDL file generated successfully at: " + wsdlFile.getAbsolutePath());
        } catch (MalformedURLException e) {
            System.err.println("Invalid WSDL URL: " + e.getMessage());
        } catch (IOException e) {
            System.err.println("Error writing WSDL file: " + e.getMessage());
        } finally {
            // 7. 停止服务,释放资源
            if (endpoint != null) {
                endpoint.stop();
                System.out.println("Service stopped.");
            }
        }
    }
}

步骤 5:运行并验证

  1. 编译项目:确保你的 Maven 项目已经编译成功。
  2. 运行 WsdlGenerator:在 IDE 中直接运行 WsdlGenerator.javamain 方法。
  3. 检查输出:你会在控制台看到类似下面的信息:
    Service published at: http://localhost:8080/ws/hello
    WSDL location: http://localhost:8080/ws/hello?wsdl
    WSDL file generated successfully at: /path/to/your/project/target/hello-world.wsdl
    Service stopped.
  4. 查看文件:去你的项目 target 目录下,你会发现 hello-world.wsdl 文件已经生成,你可以用文本编辑器或浏览器打开它,查看其内容。

使用 wsimport 工具(间接生成)

这种方法通常用于客户端开发,但也可以用来反向生成一个临时的 WSDL,它更偏向于“从 WSDL 到 Java”,而不是“从 Java 到 WSDL”,如果你有一个 Java 类,想快速得到一个符合规范的 WSDL,可以先让 wsimport 为它生成一个存根,再尝试反向工程,但这非常复杂且不推荐。

Java代码如何生成WSDL文件?-图3
(图片来源网络,侵删)

方法一(自下而上)是生成 WSDL 的标准 Java 做法

关键注解说明

  • @WebService:
    • 用在接口或类上,将其声明为一个 Web 服务。
    • name: 定义 WSDL 中 portType 的名称。
    • serviceName: 定义 WSDL 中 service 的名称。
    • targetNamespace: 定义 XML 命名空间,避免冲突,非常重要。
    • endpointInterface (用在实现类上): 明确指定该实现类所实现的接口全限定名。
  • @WebMethod:
    • 用在接口方法上,将其暴露为 Web 服务的一个操作。
    • operationName: 定义 WSDL 中 operation 的名称。
  • @WebParam:
    • 用在方法参数上,为参数指定 WSDL 中的名称。
    • name: 定义参数在 WSDL 中的名称。
方法 优点 缺点 适用场景
自下而上 (JAX-WS) 开发者只需关注 Java 代码。
框架自动处理 WSDL 的复杂性。
代码和契约同步更新。
生成的 WSDL 可能非常复杂,包含大量框架信息。
对于复杂的消息结构,可能需要手动调整注解。
快速开发和迭代,内部服务,对 WSDL 结构要求不高的场景。
自上而下 (WSDL First) WSDL 作为“契约”,定义清晰。
客户端和服务端都严格遵循契约,兼容性好。
生成的 WSDL 结构清晰、干净。
需要手动编写或维护 WSDL 文件。
契约变更时,需要同时修改 WSDL 和两端的代码。
对外发布的服务、需要严格保证接口稳定性的场景、系统集成。

对于你的问题“java 代码 生成 wsdl文件”,使用 JAX-WS 注解并编写一个生成器程序(如上面的 WsdlGenerator)是最佳实践

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