--- title: 修改代码 - 原理 created: 2026-05-18 tags: - SAP - ADT - edit - lock - activation - REST parent: "[[sap-cli/README|SAP ADT 学习笔记总览]]" prev: "[[sap-cli/02.查询代码-原理|02.查询代码 - 原理]]" next: "[[sap-cli/04.检查代码-原理|04.检查代码 - 原理]]" --- # 修改代码 — 原理 > [!abstract] 核心流程 > ADT 中修改代码遵循 **锁定 → 编辑 → 保存 → 解锁 → 激活** 的严格工作流。每一步都通过 REST API 调用对应的 ABAP 后端服务完成。 ## 1. 完整工作流 ``` ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 1.锁定 │───▶│ 2.编辑 │───▶│ 3.保存 │───▶│ 4.解锁 │───▶│ 5.激活 │ │ Lock │ │ Edit │ │ Save │ │ Unlock │ │ Activate│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ POST lock GET source PUT source POST unlock POST activate → lockHandle → 纯文本 + lockHandle + lockHandle → 激活结果 ``` > [!warning] 重要约束 > - **必须先锁定** 才能修改代码,否则 PUT 请求会被拒绝 > - **锁定句柄 (lockHandle)** 是贯穿整个编辑流程的关键凭证 > - **必须激活** 后代码才会在运行时生效(保存 ≠ 激活) ## 2. Step 1: 锁定对象 (Lock) ### 原理 ABAP 使用 **乐观锁 (Optimistic Lock)** 机制。当开发者打开一个对象进行编辑时,ADT 向后端发送锁定请求,获取一个唯一的 `lockHandle`。 ### REST API 调用 ``` POST /sap/bc/adt/oo/classes/{class_name} ?_action=LOCK &accessMode=MODIFY ``` ### 响应 ```xml ``` - 返回的 `LOCK_HANDLE` 是一个唯一标识符 - 后续的写入操作必须携带此句柄 - 锁定是 **会话级** 的,HTTP 会话断开后锁自动释放 ### 后端处理 ``` 1. ADT Framework 接收锁定请求 ↓ 2. 调用 ABAP 锁定管理器 (ENQUEUE) ↓ 3. 检查对象是否已被其他用户锁定 ↓ 4. 如果未锁定 → 创建锁定条目,返回 lockHandle 5. 如果已锁定 → 返回错误(锁定冲突) ``` ### 对应 SAP GUI | ADT 操作 | SAP GUI 等效 | |----------|-------------| | Lock 对象 | 打开 SE24/SE38 编辑模式时自动锁定 | ## 3. Step 2: 读取源代码 (Read Source) ### REST API 调用 ``` GET /sap/bc/adt/oo/classes/{class_name}/source/main Accept: text/plain ``` ### 对象路径模式 不同对象类型使用不同的路径: | 对象类型 | 路径模板 | |----------|---------| | 类 | `oo/classes/{name}/source/main` | | 程序 | `programs/programs/{name}/source/main` | | 函数模块 | `functions/groups/{group}/fmodules/{fm}/source/main` | | CDS View | `ddic/cds/views/{name}/source/main` | ### 响应 直接返回 **纯文本** 格式的 ABAP 源代码(Content-Type: `text/plain`)。 ## 4. Step 3: 写入源代码 (Write Source) ### REST API 调用 ``` PUT /sap/bc/adt/oo/classes/{class_name}/source/main Content-Type: text/plain; charset=utf-8 X-sap-adt-lockhandle: {lockHandle} <修改后的 ABAP 源代码> ``` > [!important] 关键要点 > - 请求体是 **纯文本**(不是 XML) > - **必须携带** `X-sap-adt-lockhandle` Header > - 保存 ≠ 激活:代码已写入仓库但仍处于 **非活跃状态** ### 后端处理 ``` 1. 验证 lockHandle 是否有效 ↓ 2. 将源代码写入 ABAP Repository 的非活跃版本 (Inactive Version) ↓ 3. 对象状态变为 "Modified"(在 Project Explorer 中显示 * 标记) ↓ 4. 记录到传输请求任务中(如果已分配) ``` ### 与 SAP GUI 的对比 | 特性 | SAP GUI (SE80/SE38) | ADT (Eclipse) | |------|---------------------|---------------| | 保存行为 | 保存即激活(或保存为非活跃) | 保存 ≠ 激活(显式分离) | | 锁定管理 | 隐式(打开编辑时自动锁定) | 显式(REST API 锁定/解锁) | | 版本管理 | 版本数据库 | 本地历史 + 版本数据库 | ## 5. Step 4: 解锁对象 (Unlock) ### REST API 调用 ``` POST /sap/bc/adt/oo/classes/{class_name} ?_action=UNLOCK &lockHandle={lockHandle} ``` 解锁后,其他开发者可以锁定并编辑该对象。 ## 6. Step 5: 激活对象 (Activate) ### 原理 > [!tip] 激活 vs 保存 > - **保存 (Save)**:将源代码写入仓库的非活跃版本 > - **激活 (Activate)**:编译代码并生成可执行版本(Active Version) > - 只有激活后的代码才能被运行时系统使用 ### REST API 调用 ``` POST /sap/bc/adt/activation Content-Type: application/xml ``` ### 后端激活流程 ``` 1. ADT 激活框架接收激活请求 ↓ 2. 执行预检查 (Pre-audit) ├── 语法检查 (Syntax Check) ├── 依赖检查(引用的对象是否已激活) └── 权限检查 ↓ 3. 如果预检查通过: ├── 编译 ABAP 代码 → 生成 ABAP Load ├── 更新 ABAP Repository 中的活跃版本 (Active Version) ├── 触发 ATC 检查(如果配置了自动检查) └── 将活跃版本写入传输请求 ↓ 4. 如果预检查失败: └── 返回错误列表(语法错误、缺失引用等) ``` ### 对应 SAP GUI | ADT 操作 | SAP GUI 等效 | |----------|-------------| | 激活单个对象 | `SE80` → Activate (Ctrl+F3) | | 批量激活 | `SE80` → Inactive Objects → Activate All | ## 7. 完整 REST API 调用序列示例 以下是一个修改 ABAP 类的完整 REST API 调用序列: ```python # 1. 锁定对象 lock_resp = POST("/sap/bc/adt/oo/classes/zcl_example", _action="LOCK", accessMode="MODIFY") lock_handle = parse_lock_handle(lock_resp) # 2. 读取当前源代码 source = GET("/sap/bc/adt/oo/classes/zcl_example/source/main", Accept="text/plain") # 3. 修改源代码(客户端操作) modified_source = modify_source(source) # 4. 写入修改后的源代码 PUT("/sap/bc/adt/oo/classes/zcl_example/source/main", body=modified_source, headers={"X-sap-adt-lockhandle": lock_handle}) # 5. 解锁对象 POST("/sap/bc/adt/oo/classes/zcl_example", _action="UNLOCK", lockHandle=lock_handle) # 6. 激活对象 POST("/sap/bc/adt/activation", body=activation_xml("ZCL_EXAMPLE", "/sap/bc/adt/oo/classes/zcl_example")) ``` ## 8. 错误处理 | 场景 | HTTP 状态码 | 处理方式 | |------|-----------|---------| | 对象已被锁定 | 403/409 | 提示用户等待或强制解锁 | | CSRF Token 过期 | 403 | 自动重新获取 Token 并重试 | | 语法错误 | 400 | 返回错误列表,阻止激活 | | 权限不足 | 401/403 | 检查 S_DEVELOP 权限 | ## 🔗 相关笔记 - [[sap-cli/02.查询代码-原理|02.查询代码 - 原理]] - [[sap-cli/04.检查代码-原理|04.检查代码 - 原理]] ## 📚 参考来源 - [SAP Help Portal - ADT User Guide](https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/about-abap-development-tools-user-guide) - [End-to-End SAP Automation with ADT REST Services](https://medium.com/@onuryz.itu/end-to-end-sap-automation-with-adt-rest-services-and-ai-a-modern-alternative-to-gui-scripting-343ea86064ea) - [erpl-adt (GitHub)](https://github.com/DataZooDE/erpl-adt)