QAUP_Management/doc/adxp-adapter-service-design.md

6.2 KiB
Raw Blame History

ADXP SDK Adapter Service 设计方案

背景

ADXP SDK (adxp-client-2.6.9.jar) 基于 JDK 8 编译,依赖 JDK 内部类 com.sun.xml.internal.*,无法在 Java 11+ 环境运行。主应用使用 Spring Boot 3.x必须运行在 Java 17+。

解决方案:独立适配器服务

将 SDK 隔离到独立的微服务中,运行在 JDK 8 环境,通过 REST API 提供服务。

技术栈

  • Java: JDK 8
  • 框架: Spring Boot 2.7.x (最后支持 JDK 8 的版本)
  • 构建: Maven
  • 部署: 独立进程 / Docker 容器

项目结构

adxp-adapter/
├── pom.xml                          # Maven 配置 (JDK 8, Spring Boot 2.7.x)
├── src/main/java/
│   └── com/qaup/adxp/adapter/
│       ├── AdxpAdapterApplication.java
│       ├── controller/
│       │   └── AdxpController.java  # REST API
│       ├── service/
│       │   └── AdxpSdkService.java  # SDK 封装
│       └── dto/
│           ├── LoginRequest.java
│           ├── LoginResponse.java
│           ├── MessageResponse.java
│           └── FlightMessage.java
├── src/main/resources/
│   ├── application.yml
│   └── application-prod.yml
└── libs/
    ├── adxp-client-2.6.9.jar
    └── mq.allclient-9.0.jar

API 设计

1. 登录接口

POST /api/adxp/login
Content-Type: application/json

{
  "username": "dianxin",
  "password": "dianxin@123"
}

Response:
{
  "success": true,
  "sessionId": "uuid-xxx",
  "message": "登录成功"
}

2. 接收消息接口

GET /api/adxp/messages?sessionId=xxx

Response:
{
  "success": true,
  "messages": [
    {
      "serviceCode": "ARR",
      "actionCode": "ADD",
      "content": "<xml>...</xml>"
    }
  ]
}

3. 登出接口

POST /api/adxp/logout
Content-Type: application/json

{
  "sessionId": "uuid-xxx"
}

Response:
{
  "success": true,
  "message": "登出成功"
}

配置文件

server:
  port: 8086  # 与 mock 服务器同端口,便于切换

adxp:
  # 真实数据中台配置
  host: ${ADXP_HOST:10.10.10.100}
  port: ${ADXP_PORT:7001}
  
# 安全配置(可选)
security:
  api-key: ${ADXP_ADAPTER_API_KEY:change-me-in-production}

部署方案

方案 A独立进程开发/测试)

# 使用 JDK 8 运行
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_xxx.jdk/Contents/Home
cd adxp-adapter
mvn clean package
java -jar target/adxp-adapter.jar

方案 BDocker 容器(生产推荐)

FROM openjdk:8-jdk-alpine
WORKDIR /app
COPY target/adxp-adapter.jar app.jar
COPY libs/* /app/libs/
EXPOSE 8086
ENTRYPOINT ["java", "-jar", "app.jar"]

部署:

docker build -t adxp-adapter:1.0 .
docker run -d -p 8086:8086 \
  -e ADXP_HOST=10.10.10.100 \
  -e ADXP_PORT=7001 \
  --name adxp-adapter \
  adxp-adapter:1.0

方案 CDocker Compose本地全栈

version: '3.8'
services:
  qaup-backend:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - postgres
      - redis
      - adxp-adapter
    environment:
      ADXP_SDK_HOST: adxp-adapter
      ADXP_SDK_PORT: 8086
  
  adxp-adapter:
    build: ./adxp-adapter
    ports:
      - "8086:8086"
    environment:
      ADXP_HOST: ${REAL_ADXP_HOST}
      ADXP_PORT: ${REAL_ADXP_PORT}
  
  postgres:
    image: postgis/postgis:17-3.5
    # ...
  
  redis:
    image: redis:7-alpine
    # ...

主应用集成

修改 AdxpFlightServiceClient 从调用本地 SDK 改为调用 HTTP API

@Service
@ConditionalOnProperty(name = "data.collector.adxp-adapter.host")
public class AdxpFlightServiceClient {
    
    private final RestTemplate restTemplate;
    private final FlightSdkProperties properties;
    private String sessionId;
    
    @PostConstruct
    public void afterPropertiesSet() {
        if (!isEnabled()) return;
        
        // HTTP 登录
        String url = String.format("http://%s:%d/api/adxp/login", 
            properties.getHost(), properties.getPort());
        
        LoginRequest request = new LoginRequest(
            properties.getUsername(), 
            properties.getPassword()
        );
        
        LoginResponse response = restTemplate.postForObject(
            url, request, LoginResponse.class
        );
        
        this.sessionId = response.getSessionId();
        log.info("已登录 ADXP 适配器服务: sessionId={}", sessionId);
    }
    
    public List<FlightNotificationDTO> fetchFlightNotifications() {
        String url = String.format("http://%s:%d/api/adxp/messages?sessionId=%s",
            properties.getHost(), properties.getPort(), sessionId);
        
        MessageResponse response = restTemplate.getForObject(
            url, MessageResponse.class
        );
        
        return parseMessages(response.getMessages());
    }
}

优势

  1. 兼容性隔离SDK 在 JDK 8 环境运行,主应用使用最新 Java
  2. 独立部署:可以独立升级、扩展、监控
  3. 技术栈自由:主应用可以使用 Spring Boot 3.x、Virtual Threads 等新特性
  4. 容错能力:适配器故障不影响主应用其他功能
  5. 易于替换:未来 SDK 升级或更换实现,只需修改适配器服务
  6. 开发友好:本地可以用 mock 替代,测试/生产用真实适配器

劣势

  1. 网络开销:多一次 HTTP 调用(但对于 250ms 采集间隔影响很小)
  2. 运维复杂度:多一个服务需要部署和监控
  3. 延迟增加:约 1-5ms局域网内可忽略

实施计划

Phase 1: 创建适配器服务2-3小时

  • 创建 Spring Boot 2.7.x 项目
  • 封装 SDK 为 REST API
  • 本地测试验证

Phase 2: 主应用改造1-2小时

  • AdxpFlightServiceClient 改为 HTTP 调用
  • 配置管理
  • 单元测试

Phase 3: Docker 化1小时

  • 编写 Dockerfile
  • 编写 docker-compose.yml
  • 验证容器化部署

Phase 4: 生产部署(按需)

  • 部署到测试环境验证
  • 监控和日志配置
  • 文档完善

总计

开发时间: 4-6 小时 长期收益: 技术栈现代化 + 架构清晰 + 易维护

下一步

是否需要我立即创建 adxp-adapter 项目骨架?