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

原文地址: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 守护程序类的守护程序的目标。

### 回答1: 在ABAP创建一个四则运算的函数,您可以按照以下步骤进行: 1. 创建一个Function Module:在ABAP Workbench的SE37事务,您可以创建一个名为“Z_CALCULATE”的Function Module。 2. 定义输入和输出参数:在Function Module的界面上,您可以为Function Module定义输入和输出参数。在这个例子,您可以定义以下输入和输出参数: * 输入参数: - num1(类型为I,长度为10) - num2(类型为I,长度为10) - operator(类型为C,长度为1) * 输出参数: - result(类型为I,长度为10) 3. 编写ABAP代码:在Function Module的“源代码”选项卡,您可以编写实现四则运算的ABAP代码。在这个例子,您可以使用CASE语句实现不同的运算符。以下是一个简单的示例代码: FUNCTION z_calculate. *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" VALUE(NUM1) TYPE I *" VALUE(NUM2) TYPE I *" VALUE(OPERATOR) TYPE C *" EXPORTING *" VALUE(RESULT) TYPE I *"---------------------------------------------------------------------- CASE operator. WHEN '+'. result = num1 + num2. WHEN '-'. result = num1 - num2. WHEN '*'. result = num1 * num2. WHEN '/'. IF num2 <> 0. result = num1 / num2. ELSE. result = 0. ENDIF. ENDCASE. ENDFUNCTION. 4. 测试Function Module:您可以使用SE37事务测试Function Module。在输入参数输入您想要计算的数字和运算符,然后运行Function Module。在输出参数,您将获得计算结果。 这就是在ABAP创建四则运算函数的简单步骤。 ### 回答2: 在ABAP,可以通过创建一个函数来实现四则运算。以下是一个示例: 首先,我们需要在ABAP编辑器创建一个函数模块。可以通过进入事务码`SE37`进入函数构建器界面。在这个界面,选择创建一个新的函数模块。 接下来,我们需要定义输入和输出参数。对于四则运算函数,我们需要定义四个输入参数(操作数1、操作数2、运算符、结果)以及一个输出参数(结果)。 在“接口/参数”选项卡下,点击“添加”按钮以创建输入参数。为每个输入参数分别指定一个名称、数据元素和描述。例如,对于操作数1和操作数2,可以选择INT4数据元素。 然后,点击“添加”按钮以添加输出参数。指定输出参数的名称、数据元素和描述。对于结果,也可以选择INT4数据元素。 接下来,在“源代码”选项卡下,我们需要编写ABAP代码来执行四则运算。根据输入参数指定的运算符,使用条件语句(如CASE语句)来执行相应的运算。根据运算符的不同,可以使用ABAP提供的数学函数(如ADD、SUBTRACT、MULTIPLY、DIVIDE)来执行相应的运算。将结果分配给输出参数。 最后,保存函数模块,并使用事务码`SE93`来创建一个事务代码,以便在ABAP系统调用该函数模块。 现在,我们可以在ABAP系统的任何地方使用该事务代码来调用四则运算函数。将操作数1、操作数2和运算符作为输入参数传递给函数,然后获取结果参数的值作为计算结果。 通过以上步骤,我们可以在ABAP创建一个四则运算的函数,可以在需要计算的地方方便地调用该函数。 ### 回答3: 在ABAP创建一个四则运算的函数,可以按照以下步骤进行: 1. 首先,使用函数建立一个函数模块。可以使用T-code SE37打开Function Builder。 2. 在Function Builder,选择“创建函数模块”。 3. 将函数模块命名为合适的名称,比如“四则运算”。 4. 在“接口”标签页,定义输入和输出参数。对于四则运算,我们需要定义四个输入参数(两个操作数和一个运算符)和一个输出参数(结果)。 5. 在“源代码”标签页,编写函数逻辑。首先,使用“DATA”语句定义所需的变量。然后,使用“CASE”语句根据运算符执行相应的计算操作,并将结果存储在输出参数。 6. 检查并保存函数模块。 以下是一个示例实现的函数模块的源代码: FUNCTION ZARITHMETIC. *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" VALUE(OP1) TYPE I *" VALUE(OP2) TYPE I *" VALUE(OPERATOR) TYPE C *" EXPORTING *" VALUE(RESULT) TYPE I *"---------------------------------------------------------------------- DATA: LV_RESULT TYPE I. CASE OPERATOR. WHEN '+'. LV_RESULT = OP1 + OP2. WHEN '-'. LV_RESULT = OP1 - OP2. WHEN '*'. LV_RESULT = OP1 * OP2. WHEN '/'. LV_RESULT = OP1 / OP2. WHEN OTHERS. LV_RESULT = 0. ENDCASE. RESULT = LV_RESULT. ENDFUNCTION. 通过以上步骤,我们可以成功创建一个四则运算的函数模块。之后,可以在其他ABAP程序或报表调用该函数,实现四则运算的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蓝袍先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值