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
相关产品推荐
相关产品推荐

