You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+Vert.x环境下基于JAX-WS实现SOAP服务的技术求助

在Spring Boot + Vert.x环境下整合JAX-WS实现SOAP服务及服务发现方案

我之前做过类似的整合,给你分享下具体的实现思路和方案:

一、将JAX-WS服务包装到Vert.x中的实现步骤

Vert.x本身是异步非阻塞的,而JAX-WS通常是同步处理模型,所以核心思路是把JAX-WS的同步逻辑放到Vert.x的worker线程池中执行,避免阻塞事件循环。

1. 编写标准JAX-WS服务实现

先按照常规方式创建你的SOAP服务类,和普通JAX-WS开发一致:

@WebService(serviceName = "HelloSoapService", targetNamespace = "http://your-namespace.com/")
public class HelloSoapServiceImpl {
    @WebMethod
    public String sayHello(String name) {
        return "Hello, " + name + "!";
    }
}

2. 在Vert.x中搭建HTTP服务器并转发SOAP请求

创建一个Verticle,负责启动HTTP服务器,接收SOAP请求并转发到JAX-WS处理逻辑:

public class SoapServiceVerticle extends AbstractVerticle {
    private Endpoint soapEndpoint;

    @Override
    public void start() throws Exception {
        // 初始化JAX-WS端点
        soapEndpoint = Endpoint.create(new HelloSoapServiceImpl());

        vertx.createHttpServer()
            .requestHandler(req -> {
                // 只处理POST类型的SOAP请求(Content-Type为text/xml)
                if (HttpMethod.POST.equals(req.method()) && "text/xml".equals(req.getHeader("Content-Type"))) {
                    req.bodyHandler(requestBody -> {
                        // 使用executeBlocking将同步处理逻辑委托给worker线程
                        vertx.executeBlocking(promise -> {
                            try {
                                // 构建JAX-WS消息上下文,传递请求输入流
                                ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBody.getBytes());
                                MessageContext messageContext = new WebServiceContextImpl();
                                messageContext.setMessage(MessageContext.INPUT_STREAM, inputStream);

                                // 准备输出流捕获响应
                                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                                messageContext.setMessage(MessageContext.OUTPUT_STREAM, outputStream);

                                // 调用JAX-WS端点处理请求
                                soapEndpoint.invoke(messageContext);

                                promise.complete(outputStream.toByteArray());
                            } catch (Exception e) {
                                promise.fail(e);
                            }
                        }, result -> {
                            if (result.succeeded()) {
                                req.response()
                                   .putHeader("Content-Type", "text/xml")
                                   .end(Buffer.buffer(result.result()));
                            } else {
                                req.response()
                                   .setStatusCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code())
                                   .end("SOAP Service Error: " + result.cause().getMessage());
                            }
                        });
                    });
                } else {
                    req.response().setStatusCode(HttpResponseStatus.NOT_FOUND.code()).end("Unsupported Request");
                }
            })
            .listen(8080, res -> {
                if (res.succeeded()) {
                    System.out.println("SOAP Service started on port 8080");
                } else {
                    System.err.println("Failed to start SOAP Service: " + res.cause().getMessage());
                }
            });
    }

    @Override
    public void stop() throws Exception {
        if (soapEndpoint != null) {
            soapEndpoint.stop();
        }
    }
}

3. 在Spring Boot中整合Vert.x

在Spring Boot启动类中初始化Vert.x并部署上述Verticle:

@SpringBootApplication
public class SpringBootVertxSoapApp implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootVertxSoapApp.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        // 创建Vert.x实例并部署SOAP服务Verticle
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(new SoapServiceVerticle());
    }
}

二、Vert.x中使用服务发现机制管理SOAP服务

Vert.x提供了内置的Service Discovery组件,可以轻松实现SOAP服务的注册与发现,步骤如下:

1. 添加依赖

在Maven pom.xml中加入Vert.x服务发现相关依赖:

<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-service-discovery</artifactId>
    <version>${vertx.version}</version>
</dependency>
<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-spring-boot-starter</artifactId>
    <version>${vertx.version}</version>
</dependency>

2. 注册SOAP服务到服务发现中心

修改之前的SoapServiceVerticle,在服务启动后将其注册到Service Discovery:

@Override
public void start() throws Exception {
    vertx.createHttpServer()
        .requestHandler(/* 保留之前的请求处理逻辑 */)
        .listen(8080, res -> {
            if (res.succeeded()) {
                int servicePort = res.result().actualPort();
                // 初始化服务发现实例
                ServiceDiscovery discovery = ServiceDiscovery.create(vertx);

                // 构建服务记录,自定义类型为"soap-service"便于识别
                Record soapServiceRecord = HttpEndpoint.createRecord(
                    "hello-soap-service",
                    "localhost",
                    servicePort,
                    "/HelloSoapService"
                )
                .setType("soap-service")
                .setMetadata(new JsonObject().put("serviceName", "HelloSoapService"));

                // 发布服务到发现中心
                discovery.publish(soapServiceRecord, publishRes -> {
                    if (publishRes.succeeded()) {
                        System.out.println("SOAP Service registered to discovery center");
                    } else {
                        System.err.println("Failed to register service: " + publishRes.cause().getMessage());
                    }
                });
            }
        });
}

3. 发现并调用SOAP服务

在需要调用SOAP服务的客户端,通过Service Discovery查找服务并调用:

// 初始化服务发现实例
ServiceDiscovery discovery = ServiceDiscovery.create(vertx);

// 设置过滤条件,查找指定类型和名称的SOAP服务
DiscoveryOptions discoveryOpts = new DiscoveryOptions()
    .setFilter(record -> "soap-service".equals(record.getType()) &&
        "HelloSoapService".equals(record.getMetadata().getString("serviceName")));

discovery.getRecord(discoveryOpts, res -> {
    if (res.succeeded() && res.result() != null) {
        Record serviceRecord = res.result();
        // 构建SOAP服务的WSDL地址
        String wsdlUrl = String.format("http://%s:%d%s?wsdl",
            serviceRecord.getLocation().getString("host"),
            serviceRecord.getLocation().getInteger("port"),
            serviceRecord.getLocation().getString("path"));

        // 使用JAX-WS客户端调用服务
        try {
            URL url = new URL(wsdlUrl);
            QName serviceQName = new QName("http://your-namespace.com/", "HelloSoapService");
            Service jaxWsService = Service.create(url, serviceQName);
            HelloSoapServiceImpl servicePort = jaxWsService.getPort(HelloSoapServiceImpl.class);

            String response = servicePort.sayHello("Vert.x SOAP");
            System.out.println("SOAP Response: " + response);
        } catch (Exception e) {
            System.err.println("Failed to call SOAP service: " + e.getMessage());
        } finally {
            // 释放服务引用
            discovery.releaseServiceObject(serviceRecord);
        }
    } else {
        System.err.println("SOAP Service not found: " + res.cause().getMessage());
    }
});

关键注意事项

  • 避免阻塞事件循环:JAX-WS的同步处理必须放在executeBlocking或Worker Verticle中执行,否则会拖慢整个Vert.x应用的性能。
  • 服务健康检查:可以给注册的服务记录添加健康检查逻辑,确保服务发现中心能及时剔除不可用的服务实例。
  • 上下文路径匹配:确保HTTP服务器的请求路径和JAX-WS服务的上下文路径一致,避免404错误。

内容的提问来源于stack exchange,提问作者Meiyappan Kannappa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:08:35