继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

如何在 Spring Boot 中将 SOAP Web Service 转换为 RESTful API

王家大少
关注TA
已关注
手记 50
粉丝 27
获赞 81

在现代微服务架构中,RESTful API 是主流,但很多遗留系统(Legacy Systems)或第三方服务仍然使用 SOAP 协议。当我们想要重构系统或为前端提供标准 REST 接口时,就需要在两者之间架起一座桥梁。

本文将手把手教你如何使用 Spring Boot 构建一个“适配器层”,将传统的 SOAP 服务封装并转换为现代的 RESTful 接口。

🏗️ 核心架构思路

我们的目标不是重写 SOAP 服务,而是创建一个代理层(Adapter Layer)

  1. REST 控制器:接收前端的 JSON 请求。
  2. 转换逻辑:将 JSON 参数转换为 SOAP 请求对象。
  3. SOAP 客户端:调用旧的 Web Service。
  4. 响应映射:将 SOAP 返回的 XML 对象转换为 JSON DTO 返回给前端。

🛠️ 第一步:引入依赖

pom.xml 中,我们需要引入 Spring Web(用于 REST)和 Spring Web Services(用于 SOAP 客户端支持)。

<dependencies>
    <!-- 用于开发 REST 接口 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 用于调用 SOAP 服务 (JAX-WS 支持) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web-services</artifactId>
    </dependency>
    
    <!-- Lombok (可选,简化代码) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

在实际项目中,SOAP 的类通常是根据 WSDL 自动生成的。为了演示,我们手动模拟两个类:一个是 SOAP 服务端返回的复杂对象,一个是 REST 客户端想要的简洁对象。

1. 模拟 SOAP 服务端返回的对象

package com.example.soapclient;

import jakarta.xml.bind.annotation.*;

// 模拟 SOAP 响应中的复杂对象
@XmlRootElement(name = "UserResponse", namespace = "http://example.com/soap")
public class SoapUserResponse {
    private String userId;
    private String fullName;
    private String emailAddress;

    // 构造函数、Getter 和 Setter 省略 (实际开发中由 IDE 生成或 Lombok)
    public SoapUserResponse() {}
    public SoapUserResponse(String userId, String fullName, String emailAddress) {
        this.userId = userId;
        this.fullName = fullName;
        this.emailAddress = emailAddress;
    }
    // ... getters and setters
    public String getUserId() { return userId; }
    public String getFullName() { return fullName; }
    public String getEmailAddress() { return emailAddress; }
}

2. 定义 REST 接口返回的 DTO

package com.example.restapi;

// REST 客户端接收的简洁 JSON 对象
public class UserDTO {
    private String id;
    private String name;
    // 注意:SOAP 中有 email,但 REST 接口决定不暴露这个字段,实现数据脱敏

    public UserDTO() {}
    public UserDTO(String id, String name) {
        this.id = id;
        this.name = name;
    }
    // ... getters and setters
    public String getId() { return id; }
    public String getName() { return name; }
}

这个组件负责真正去调用旧的 Web Service。在实际场景中,这里会使用 WebServiceTemplate 进行 XML 通信。

package com.example.soapclient;

import org.springframework.stereotype.Component;
import org.springframework.ws.client.core.WebServiceTemplate;

@Component
public class LegacySoapClient {

    private final WebServiceTemplate webServiceTemplate;

    public LegacySoapClient(WebServiceTemplate webServiceTemplate) {
        this.webServiceTemplate = webServiceTemplate;
    }

    /**
     * 模拟调用远程 SOAP 服务获取用户信息
     */
    public SoapUserResponse getUserFromSoapService(String userId) {
        System.out.println(">>> 正在调用 SOAP 服务,获取用户 ID: " + userId);
        
        // 【实际代码示例】:
        // return (SoapUserResponse) webServiceTemplate.marshalSendAndReceive(
        //     "http://localhost:8080/soap-service", 
        //     new GetUserRequest(userId)
        // );

        // 这里直接返回一个模拟的 SOAP 响应对象用于演示
        return new SoapUserResponse(userId, "张三 (来自 SOAP)", "zhangsan@old-system.com");
    }
}

这是最关键的一步。我们创建一个标准的 Spring MVC 控制器,在内部注入 SOAP 客户端,完成“翻译”工作。

package com.example.restapi;

import com.example.soapclient.LegacySoapClient;
import com.example.soapclient.SoapUserResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/users")
public class UserRestAdapter {

    private final LegacySoapClient legacySoapClient;

    // 注入 SOAP 客户端
    public UserRestAdapter(LegacySoapClient legacySoapClient) {
        this.legacySoapClient = legacySoapClient;
    }

    /**
     * REST 接口: GET /api/v1/users/{id}
     * 内部逻辑: 接收 REST 请求 -> 调用 SOAP -> 转换数据 -> 返回 JSON
     */
    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUser(@PathVariable String id) {
        
        // 1. [调用] 委托给 SOAP 客户端
        SoapUserResponse soapResponse = legacySoapClient.getUserFromSoapService(id);

        // 2. [转换] SOAP 响应对象 -> REST DTO
        UserDTO userDTO = convertToDTO(soapResponse);

        // 3. [响应] 返回 JSON
        return ResponseEntity.ok(userDTO);
    }
    
    /**
     * 数据映射方法:负责字段过滤和重命名
     */
    private UserDTO convertToDTO(SoapUserResponse soapUser) {
        UserDTO dto = new UserDTO();
        dto.setId(soapUser.getUserId());
        dto.setName(soapUser.getFullName());
        // 故意忽略 emailAddress 字段,实现字段过滤
        return dto;
    }
}

⚙️ 第五步:配置类

为了让 WebServiceTemplate 能够处理 XML 和 Java 对象的转换,我们需要配置一个 Marshaller。

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.client.core.WebServiceTemplate;

@Configuration
public class SoapConfig {

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        // 指定包含 JAXB 注解(@XmlRootElement)的包路径
        marshaller.setPackagesToScan("com.example.soapclient");
        return marshaller;
    }

    @Bean
    public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller) {
        WebServiceTemplate template = new WebServiceTemplate();
        template.setMarshaller(marshaller);
        template.setUnmarshaller(marshaller);
        return template;
    }
}

🧪 测试与验证

启动 Spring Boot 应用后,我们可以使用 Postman 或 curl 进行测试。

请求:

GET http://localhost:8080/api/v1/users/1001

控制台日志:

>>> 正在调用 SOAP 服务,获取用户 ID: 1001

响应结果 (JSON):

{
  "id": "1001",
  "name": "张三 (来自 SOAP)"
}

通过这种方式,我们成功实现了:

  • 协议解耦:前端不再依赖复杂的 SOAP XML,而是使用轻量级的 JSON。
  • 接口现代化:将 SOAP 的过程式调用(通常只有 POST)转换为了符合 REST 风格的资源操作(GET /users/{id})。
  • 数据脱敏:在 convertToDTO 方法中,我们可以灵活地隐藏 SOAP 返回的敏感字段(如 email),只暴露必要信息。

这种“适配器模式”是遗留系统重构中最稳妥、最常用的手段之一。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP