在ABAP中创建一个简单的守护进程

本文详细介绍了如何在ABAP中使用ABAPDaemon框架创建一个简单的守护进程,包括步骤、方法实现和应用场景,涵盖了从基础类继承、事件响应到PCP通信的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:Create a simple Daemon in ABAP

一、ABAP语言中的守护进程是什么?

守护程序是一种实用程序,它自身连续运行,无需交互式用户在后台多任务操作系统上的控制,以监视和处理某些子系统或对事件立即做出反应。守护进程在预定义的时间或响应某些事件执行显式操作。

ABAP 守护进程框架 (ADF-ABAP Daemon Framework) 提供的 ABAP 守护进程功能与 Linux 或 Windows 中的对应功能更加相似。它们通过在具有无限生命周期的会话中运行来以可靠的方式处理事件。ABAP 程序可以通过使用 ABAP 消息传递通道和消息类型推送通道协议 (PCP) 向守护程序发送消息来与守护程序进行通信,PCP 是一种类似于简单 HTTP 消息的通信格式。

守护进程对错误的应对非常可靠,即守护进程会话在遇到错误(E/A/X 消息)后不会终止。但是,每次运行时错误或类型 E、A 或 X 的消息导致程序终止时,都会自动再次创建 ABAP 守护程序。当其 AS 实例关闭时,可以通过创建包含与前面的守护程序相同的上下文信息的新守护程序来将守护程序移动到另一个 AS 实例。这使得新的守护进程能够完成相同的工作。

二、ABAP 守护进程框架 (ADF)

SAP Netweaver 7.52 将 ABAP Daemon Framework 或简称 ADF 作为一项新功能。ADF 是一个 API,允许您在 ABAP 中创建和管理守护程序。ABAP 守护进程是 ABAP 守护进程类的实例,位于应用程序服务器的特殊 ABAP 守护进程会话中。ABAP程序本身使用ABAP守护进程管理器来访问ABAP守护进程。

如前所述,ABAP 守护进程的处理发生在后台并使用事件进行控制。守护程序或ABAP运行时框架的用户可以引发ABAP守护程序事件,守护程序使用预定义的接口方法对此做出反应。守护进程必须始终准备好对入站事件做出反应,这是通过以非阻塞模式运行 ABAP 守护进程处理来确保的,以防止 ABAP 守护进程处理中出现运行时错误 DAEMON_ILLEGAL_STATEMENT 以及随后重新启动守护进程。

有关ADF实现和 ABAP 守护进程类的详细信息扩展可以在 ABAP 关键字文档本博客文章系列中找到。在这里我想更多地关注如何通过实现守护进程类来创建守护进程的过程。

三、ABAP 守护进程类

ABAP守护进程类是一个全局类,继承自抽象系统类CL_ABAP_DAEMON_EXT_BASE。ABAP 守护程序类继承了接口 IF_ABAP_DAEMON_EXTENSION 的方法,如果在 ABAP 守护程序类中实现了这些事件,则ABAP 守护程序类将使用这些方法对ABAP 守护程序事件做出反应。这些方法的详细解释可以在文档的相关部分找到。

ABAP 守护程序类可以包含更多辅助方法,并且可以在其方法中调用任意数量的其他过程。还可以实现接口 IF_ABAP_TIMER_HANDLER 将 ABAP 守护程序类转换为 ABAP 计时器处理程序,从而对 ABAP 计时器事件做出反应。例如,等待某些事件或在一段时间后停止守护进程。当从 ABAP 守护进程类实例化 ABAP 守护进程时,ABAP 守护进程框架将创建 ABAP 守护进程会话。

四、创建一个简单的ABAP守护进程

现在让我们创建 ABAP 守护进程并使用 PCP 消息与它们交互。如前所述,ABAP 守护进程是扩展基类 CL_ABAP_DAEMON_EXT_BASE 的 ABAP 守护进程类的实例。因此,首先我们需要按照本教程定义类

步骤1:创建一个新的ABAP Daemon类

第一步,创建一个 ABAP 类 ZCL_ABAP_SIMPLE_DAEMON 并将 CL_ABAP_DAEMON_EXT_BASE 设置为超类。从这个超类中,我们的守护进程将从 IF_ABAP_DAEMON_EXTENSION 接口继承不同的方法,这将允许我们响应不同的事件。现在您会看到必须重新定义的 9 个继承方法的列表。
在这里插入图片描述
图1 : 必须重新定义的 IF_ABAP_DAEMON_EXTENSION 接口的继承方法列表。

步骤2:实现ON_ACCEPT方法

在创建 ABAP 守护程序类的新实例之前,将调用其 ON_ACCEPT 方法来确定是否应启动该守护程序。它接受来自您自己的类的所有启动请求,并拒绝来自任何其他程序的所有请求。这是通过检查发起启动的调用程序来实现的。

METHOD if_abap_daemon_extension~on_accept.
  TRY.
      DATA lv_program_name TYPE program.
      lv_program_name = cl_oo_classname_service=>get_classpool_name( 'ZCL_ABAP_SIMPLE_DAEMON' ).

      IF i_context_base->get_start_caller_info( )-program = lv_program_name.
        e_setup_mode = co_setup_mode-accept.
      ELSE.
        e_setup_mode = co_setup_mode-reject.
      ENDIF.
    CATCH cx_abap_daemon_error.
      " to do: for productive applications, error handling, e.g. write error log!
      e_setup_mode = co_setup_mode-reject.
  ENDTRY.
ENDMETHOD.

第三步:实现ON_START方法

要启动ABAP守护进程,需要执行ON_START方法。您可以包含一条 PCP 消息,其中包含可在 ON_START 方法中访问的任意启动参数。

在这个简单的场景中,您将通过 PCP 传递参数超时。然后,守护进程将设置一个计时器,以便在每次达到超时时显示弹出消息。计数器将用于在五个消息后停止计时器。

首先,您需要创建一些私有成员变量来存储必要的数据。将这些行添加到类的 PRIVATE SECTION 中:

private section.
DATA: mv_timeout TYPE i,
      mo_timer   TYPE REF TO if_abap_timer_manager,
      mv_counter TYPE i.

您还需要添加 IF_ABAP_TIMER_HANDLER 作为守护程序类的接口。在 ON_START 方法中,您现在可以从 PCP 检索超时值,然后启动计时器。为此,请复制以下实现:

METHOD if_abap_daemon_extension~on_start.
  TRY.
      " retrieve timeout from PCP start parameters
      mv_timeout = i_context->get_start_parameter( )->get_field( 'timeout' ).

      " start timer for displaying messages
      mo_timer = cl_abap_timer_manager=>get_timer_manager( ).
      mo_timer->start_timer( i_timeout = mv_timeout i_timer_handler = me ).

    CATCH cx_abap_daemon_error cx_ac_message_type_pcp_error cx_abap_timer_error.
      " to do: for productive applications, error handling, e.g. write error log!
  ENDTRY.
ENDMETHOD.

第四步:实现ON_TIMEOUT方法

当你的ABAP守护进程在后台运行时,当超时时间过去时,ON_TIMEOUT方法将被触发。因此,您需要为类的 PUBLIC SECTION 实现一个处理程序接口 if_abap_timer_handler。通过在类中实现以下 ON_TIMEOUT 方法,将显示使用功能模块 TH_POPUP 的弹出消息,并且计时器将重新启动五次:

METHOD if_abap_timer_handler~on_timeout.
  " increment the loop counter
  ADD 1 TO mv_counter.

  " display popup message
  CALL FUNCTION 'TH_POPUP'
    EXPORTING
      client  = sy-mandt
      user    = sy-uname
      message = CONV th_popup( |Timeout triggered. Number of loops: { mv_counter }| ).

  " restart the timer if any loops are remaining
  IF mv_counter < 5.
    TRY.
        mo_timer->start_timer( i_timeout = mv_timeout i_timer_handler = me ).
      CATCH cx_abap_timer_error.
        " to do: for productive applications, error handling, e.g. write 
error log!
    ENDTRY.
  ENDIF.
ENDMETHOD.

当守护进程在后台持续运行时,您还可以向它发送 PCP 消息。

第5步:实现ON_MESSAGE方法

ON_MESSAGE 是一个有用的方法,守护进程通过它接收用户输入并做出响应。每次守护进程收到 PCP 消息时都会调用 ON_MESSAGE 方法。当守护进程接收到用户输入时,将弹出一个弹出对话框,该对话框显示在 SAPGUI 中。

METHOD if_abap_daemon_extension~on_message.
  TRY.
      " get text from PCP message
      DATA(lv_text) = i_message->get_text( ).

      " display popup
      CALL FUNCTION 'TH_POPUP'
        EXPORTING
          client  = sy-mandt
          user    = sy-uname
          message = CONV th_popup( |Message received: { lv_text }| ).
    CATCH cx_ac_message_type_pcp_error.
      " to do: for productive applications, error handling, e.g. write error log!
  ENDTRY.
ENDMETHOD.

您必须考虑这样一个事实:只有运行守护程序的程序才能通过管理器守护程序使用该守护程序。这个想法是通过守护进程类本身创建守护进程。因此,您需要向该类添加另外 3 个方法:START、SEND 和 STOP 来管理守护进程。

第6步:实现静态方法START

这个简单的 ABAP 守护进程将通过静态方法启动。因此,您需要在守护程序类中创建一个带有两个导入参数的新方法 START:

IV_DAEMON_NAME:守护进程的名称
IV_TIMEOUT:两个连续定时器事件之间的超时时间(毫秒)

为此,请将以下代码粘贴到类定义的 PUBLIC SECTION 中:

CLASS-METHODS start
  IMPORTING
    iv_daemon_name TYPE string
    iv_timeout     TYPE i
  RAISING
    cx_abap_daemon_error
    cx_ac_message_type_pcp_error.

使用 ABAP 守护程序管理器实例化 ABAP 守护程序。此方法包装类 CL_ABAP_DAEMON_CLIENT_MANAGER 的方法 START 并启动 ABAP 守护程序类的 ABAP 守护程序。其静态方法 CL_ABAP_DAEMON_CLIENT_MANAGER=>START 需要守护程序的名称和优先级作为参数。此外,您还可以将启动参数作为 PCP 消息传递。

METHOD start.
  " set ABAP Daemon start parameters
  DATA(lo_pcp) = cl_ac_message_type_pcp=>create( ).
  lo_pcp->set_field( i_name = 'timeout' i_value = CONV #( iv_timeout ) ).

  " start the daemon application using the ABAP Daemon Manager
  cl_abap_daemon_client_manager=>start(
      i_class_name = 'ZCL_ABAP_SIMPLE_DAEMON'
      i_name       = CONV #( iv_daemon_name )
      i_priority   = cl_abap_daemon_client_manager=>co_session_priority_low
      i_parameter  = lo_pcp ).
ENDMETHOD.

检查所有调用者以确保该方法仅在相关程序和 ABAP 守护程序类中使用。已启动守护进程的 ID 会被保存以供进一步使用。如果ABAP守护进程类在启动时被接受,则返回值不是初始值。

第7步:实现静态方法SEND并运行守护进程

实现一个静态方法 SEND,它将用于向守护进程发送文本,从而触发其 ON_MESSAGE 方法。该方法需要以下导入参数:

IV_DAEMON_NAME:将接收消息的守护进程的名称。

IV_TEXT:将发送到守护程序的文本消息。

将以下代码粘贴到类定义的公共部分中。


CLASS-METHODS send
  IMPORTING
    iv_daemon_name TYPE string
    iv_text        TYPE string
  RAISING
    cx_abap_daemon_error
    cx_ac_message_type_pcp_error.

要将 PCP 消息发送到守护程序,您需要检索类 ZCL_ABAP_SIMPLE_DAEMON 的所有正在运行的 ABAP 守护程序实例的列表。然后,您可以将每个实例的名称与 IV_DAEMON_NAME 进行比较,并相应地发送 PCP 消息。

METHOD send.
  " retrieve the list of ABAP Daemon instances
  DATA(lt_ad_info) = cl_abap_daemon_client_manager=>get_daemon_info( i_class_name = 'ZCL_ABAP_SIMPLE_DAEMON').

  " create PCP message with text
  DATA(lo_pcp) = cl_ac_message_type_pcp=>create( ).
  lo_pcp->set_text( iv_text ).

  " for each running daemon instance of this class
  LOOP AT lt_ad_info ASSIGNING FIELD-SYMBOL(<ls_info>).

    " send a message if the names match
    IF iv_daemon_name = <ls_info>-name.
      cl_abap_daemon_client_manager=>attach( <ls_info>-instance_id )->send( lo_pcp ).
    ENDIF.

  ENDLOOP.
ENDMETHOD.

现在,您只需调用之前创建的静态 START 方法即可启动守护程序。因此,只需一行代码即可创建一个新的ABAP程序Z_ABAP_SIMPLE_DAEMON_START

REPORT Z_ABAP_SIMPLE_DAEMON_START.
zcl_ABAP_simple_daemon=>start( iv_daemon_name = 'simple_daemon' iv_timeout = 10000 ).

您应该每 10 秒看到一个弹出通知:
在这里插入图片描述

第 8 步:停止 ABAP 守护进程

您可以使用 SAPGUI 中的事务 SMDAEMON 监视所有正在运行的 ABAP 守护程序。在那里你可以看到它们的状态,检查错误,甚至重新启动,并终止它们。

要停止守护程序,请从列表中选择它,然后转至 ABAP 守护程序 > 终止守护程序。或者,您也可以创建静态 STOP 方法。因此,将其添加到类定义的公共部分:

  CLASS-METHODS stop
  IMPORTING
    iv_daemon_name TYPE string
  RAISING
    cx_abap_daemon_error.

并实现方法

METHOD stop.
  " retrieve the list of ABAP Daemon instances
  DATA(lt_ad_info) = cl_abap_daemon_client_manager=>get_daemon_info( i_class_name = 'ZCL_ABAP_SIMPLE_DAEMON').

  " for each running daemon instance of this class
  LOOP AT lt_ad_info ASSIGNING FIELD-SYMBOL(<ls_info>).

    " stop the daemon if the names match
    IF iv_daemon_name = <ls_info>-name.
        cl_abap_daemon_client_manager=>stop( i_instance_id = <ls_info>-instance_id ).
    ENDIF.

  ENDLOOP.
ENDMETHOD.

该方法包装了 CL_ABAP_DAEMON_CLIENT_MANAGER 类的 STOP 方法,用于停止 ABAP 守护进程。现在你可以通过执行来停止你的守护进程

zcl_ABAP_simple_daemon=>stop( iv_daemon_name = 'simple_daemon' ).

来自任何 ABAP 程序。更多示例也可以在文档中找到。

五、守护进程用例。

正如这篇博客文章中很好地解释的那样,守护进程的主要用例是处理事件或管理简单的后台活动以及频繁的定期任务,例如跟踪、日志记录、资源清理等,而不会损害 LUW(逻辑工作单元-Logical Unit of Work)。

六、结论

我希望这个分步说明可以帮助您对守护进程以及如何创建守护进程有一些了解。您还可以通过重新定义其他方法来扩展此示例,以应对系统重新启动或服务器关闭的情况。例如,当服务器关闭时,会触发开发者实现的ON_SERVER_SHUTDOWN方法。当当前 AS 实例关闭时,此方法调用帮助器方法 RELOCATE 将守护程序移动到不同的 AS 实例。

 method IF_ABAP_DAEMON_EXTENSION~ON_SERVER_SHUTDOWN.
 relocate( ).
 endmethod.

relocate 方法必须从当前 AS ABAP 的列表中随机选择一个 AS 实例。然后,该应用程序服务器用作启动当前 ABAP 守护程序类的守护程序的目标。

<think>嗯,用户想知道在SAP中进行代码增强的方法和实现方式。我需要先回顾一下SAP的代码增强框架,不同的增强方式。首先,SAP有多种增强技术,比如用户出口(User Exits)、BADIs(Business Add-Ins)、隐式增强、显式增强,还有BTE(Business Transaction Events)之类的。可能还要提到Enhancement Framework,这是比较新的增强方式,包括类增强和方法增强。 用户提供的引用里有提到类增强,包括隐式和显式,还有Pre-Exit、Post-Exit、Overwrite-Exit这些类型。引用1里提到了SAP ABAP增强框架中的类和方法增强,所以这部分需要详细说明。另外,引用3提到了BTE的实现方式,使用事务码FIBF和对应的函数模块。还有引用2提到的守护进程,可能和增强关系不大,但需要确保不遗漏相关信息。 需要分点回答,先概述主要的增强方法,然后逐一介绍每种方法的具体实现步骤。例如,用户出口通常是在程序中预留的钩子,用户可以在SE80中找到并添加代码。BADIs则是基于面向对象的增强,使用SE19创建实现。Enhancement Framework允许在类、方法、函数组等处进行隐式或显式增强,使用SE24或SE80中的Enhancement选项。BTE通过FIBF配置,调用自定义函数模块。最后,隐式增强可能在结构、函数组或全局类中存在,使用Enhancement Spot激活。 还要注意用户提到的系统级指令,比如行内数学表达式用$...$,但这里可能用不上。需要生成相关问题,比如各种增强方法的区别、实际案例,或者如何选择增强方式。同时要确保引用正确,引用1、3的相关内容需要自然插入到回答中,比如在类增强和BTE部分添加引用标记。 现在需要组织信息,结构清晰,先总述再分点,每种方法给出事务码和步骤。确保语言简洁,符合中文回答,并且每个引用出现在对应的内容末尾。检查是否有遗漏的方法,比如可能还有Enhancement Points或Source Code Plugins,但用户提供的引用里没有提到这些,所以可能不需要涉及。最后生成的相关问题要围绕用户可能感兴趣的后续问题展开,比如比较不同方法,实际应用场景,调试技巧等。</think>### SAP 代码增强方法及实现方式分步说明 SAP代码增强的核心目标是**扩展标准功能而不修改原生代码**。以下是主流增强方法及实现步骤: --- #### 一、Enhancement Framework(增强框架) 1. **隐式增强** - **触发位置**:标准程序、函数组、全局类的预定义增强点 - **实现步骤**: 1. 使用事务码`SE24`或`SE80`打开目标类/程序 2. 右键选择 **Enhancement -> Edit** 3. 在弹出窗口中选择 **Pre-Exit**(前置增强)、**Post-Exit**(后置增强)或 **Overwrite-Exit**(覆盖增强) 4. 编写增强代码并激活[^1] 2. **显式增强** - **适用场景**:需要自定义增强点 - **实现步骤**: 1. 创建Enhancement Spot(事务码`SE24`) 2. 定义增强点(Enhancement Point)或增强段(Enhancement Section) 3. 通过`SE80`在目标程序中插入增强点代码 ```abap ENHANCEMENT-POINT <ep_name> SPOTS <spot_name>. ``` --- #### 二、BADI(Business Add-Ins) 1. **查找BADI** - 使用事务码`SE18`查看标准BADI定义 - 通过事务码`SE24`查看接口`IF_EX_<BADI_NAME>` 2. **实现BADI** 1. 事务码`SE19`创建新实现 2. 选择接口方法并编写增强逻辑 3. 激活后通过过滤器(Filter Value)控制调用条件 --- #### 三、用户出口(User Exits) 1. **标准出口** - 查找方法:事务码`SMOD`输入功能模块名(如`EXIT_<程序名>_001`) - 实现步骤: 1. 通过`CMOD`创建增强项目 2. 分配出口函数模块 3. 在函数模块`ZX<XXXX>U01`中编写代码 2. **字段/屏幕出口** - 使用`SPRO`配置路径:**附加程序 -> 字段/屏幕增强** --- #### 四、BTE(Business Transaction Events) 1. **配置步骤** 1. 事务码`FIBF`选择事件编号(如`00001120`凭证过账增强) 2. 激活事件并绑定自定义函数模块 3. 在函数模块中实现逻辑(示例函数名:`Z_FIBF_XXXX`)[^3] --- #### 五、隐式增强点(Source Code Plugins) - **触发位置**:结构、函数组或全局类中预留的`INCLUDE`程序 - **操作方法**: 1. 使用`SE38`打开包含程序(如`LXXXTOP`) 2. 通过`Enhancement Operations`插入代码 --- ### 增强方法对比 | 方法 | 适用场景 | 维护性 | 复杂度 | |--------------------|-------------------------|----------|--------| | Enhancement Frame | 类/方法级增强 | 高 | 中 | | BADI | 业务逻辑扩展 | 高 | 低 | | BTE | 财务/物流事务增强 | 中 | 高 | | 用户出口 | 简单字段/逻辑扩展 | 低 | 低 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝袍先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值