01
前言
SAP与外围系统做接口时,有一种设计模式如下:
SAP设置一个通用接口,外围系统传入接口编号(映射到SAP中某个SE37函数),传入函数的入参JSON字符串,SAP函数执行完后,将结果序列化成JSON返回给外围系统,这里可能就会涉及到函数的动态调用,下面用一个实例来介绍具体使用方法。
02
准备SE37函数
FUNCTION zrfc_say_hello.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(IV_VALUE) TYPE STRING
*" EXPORTING
*" VALUE(EV_VALUE) TYPE STRING
*" TABLES
*" IT_INPUT STRUCTURE T001W OPTIONAL
*" ET_OUTPUT STRUCTURE T001W OPTIONAL
*" EXCEPTIONS
*" INVALID_PARAM
*"----------------------------------------------------------------------
IF iv_value IS INITIAL.
RAISE invalid_param.
ENDIF.
ev_value = |Hello { iv_value }! From sap { sy-datum }{ sy-uzeit }|.
SELECT * INTO TABLE @et_output FROM t001w UP TO 10 ROWS FOR ALL ENTRIES IN @it_input WHERE werks = @it_input-werks.
ENDFUNCTION.
03
SE38 Demo程序
*&---------------------------------------------------------------------*
Report zyxstest01
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zyxstest01.
"SE37函数名称
CONSTANTS cns_name TYPE eu_lname VALUE 'ZRFC_SAY_HELLO'.
"入参json字符串
DATA lv_json_in TYPE string.
"出参json字符串
DATA lv_json_out TYPE string.
"入参对象引用
DATA lo_data_in TYPE REF TO data.
"出参对象引用
DATA lo_data_out TYPE REF TO data.
"结构组件,用来创建动态结构
DATA lt_components TYPE abap_component_tab.
DATA ls_components TYPE abap_componentdescr.
DATA lo_datadescr TYPE REF TO cl_abap_datadescr.
DATA lo_struct TYPE REF TO cl_abap_structdescr.
"函数动态参数明细
DATA ls_interface TYPE rsfbintfv.
"函数动态调用时传参
DATA lt_param TYPE abap_func_parmbind_tab.
DATA ls_param TYPE abap_func_parmbind.
"函数动态调用时异常参数
DATA lt_except TYPE abap_func_excpbind_tab.
DATA ls_except TYPE abap_func_excpbind.
<fs_data_in>, :
<fs_data_out>,
<fs_value>.
lv_json_in = '{"IV_VALUE":"JAVA","IT_INPUT":[{"WERKS":"1000"},{"WERKS":"2000"}]}'.
"获取函数参数
cl_fb_function_utility=>meth_get_interface( EXPORTING im_name = cns_name IMPORTING ex_interface = ls_interface ).
"导入参数
LOOP AT ls_interface-import INTO DATA(ls_import).
ls_import-parameter. =
?= cl_abap_datadescr=>describe_by_name( p_name = ls_import-structure ).
APPEND ls_components TO lt_components.
ENDLOOP.
"更改参数
LOOP AT ls_interface-change INTO DATA(ls_change).
ls_change-parameter. =
?= cl_abap_datadescr=>describe_by_name( p_name = ls_change-structure ).
APPEND ls_components TO lt_components.
ENDLOOP.
"表参数
LOOP AT ls_interface-tables INTO DATA(ls_table).
ls_table-parameter. =
lo_datadescr ?= cl_abap_datadescr=>describe_by_name( p_name = ls_table-structure ).
"根据行结构创建表结构
CALL METHOD cl_abap_tabledescr=>create
EXPORTING
p_line_type = lo_datadescr
RECEIVING
p_result = ls_components-type.
APPEND ls_components TO lt_components.
ENDLOOP.
"创建入参结构
CALL METHOD cl_abap_structdescr=>create
EXPORTING
p_components = lt_components
RECEIVING
p_result = lo_struct.
CREATE DATA lo_data_in TYPE HANDLE lo_struct.
ASSIGN lo_data_in->* TO <fs_data_in>.
"解析入参JSON
CALL METHOD /ui2/cl_json=>deserialize
EXPORTING
json = lv_json_in
CHANGING
data = lo_data_in.
"构造函数动态调用参数
"入参
LOOP AT ls_interface-import INTO ls_import.
ASSIGN COMPONENT ls_import-parameter OF STRUCTURE <fs_data_in> TO <fs_value>.
CHECK sy-subrc = 0.
ls_import-parameter. =
abap_func_exporting. =
REF #( <fs_value> ). =
INSERT ls_param INTO TABLE lt_param.
CLEAR ls_param.
ENDLOOP.
"更改参数
LOOP AT ls_interface-change INTO ls_change.
ASSIGN COMPONENT ls_change-parameter OF STRUCTURE <fs_data_in> TO <fs_value>.
CHECK sy-subrc = 0.
ls_change-parameter. =
abap_func_changing. =
REF #( <fs_value> ). =
INSERT ls_param INTO TABLE lt_param.
CLEAR ls_param.
ENDLOOP.
"表参数
LOOP AT ls_interface-tables INTO ls_table.
ASSIGN COMPONENT ls_table-parameter OF STRUCTURE <fs_data_in> TO <fs_value>.
CHECK sy-subrc = 0.
ls_table-parameter. =
abap_func_tables. =
REF #( <fs_value> ). =
INSERT ls_param INTO TABLE lt_param.
CLEAR ls_param.
ENDLOOP.
"出参
LOOP AT ls_interface-export INTO DATA(ls_export).
ls_export-parameter. =
abap_func_importing. =
CREATE DATA ls_param-value TYPE (ls_export-structure).
INSERT ls_param INTO TABLE lt_param.
CLEAR ls_param.
ENDLOOP.
"异常,不传的话,函数抛出异常的时候会DUMP
LOOP AT ls_interface-except INTO DATA(ls_exce).
ls_exce-parameter. =
sy-tabix. =
INSERT ls_except INTO TABLE lt_except.
CLEAR ls_except.
ENDLOOP.
"动态调用Function
CALL FUNCTION cns_name
lt_param
lt_except.
IF sy-subrc = 0.
"创建出参结构
REFRESH lt_components.
"导出参数
LOOP AT ls_interface-export INTO ls_export.
ls_export-parameter. =
?= cl_abap_datadescr=>describe_by_name( p_name = ls_export-structure ).
APPEND ls_components TO lt_components.
ENDLOOP.
"更改参数
LOOP AT ls_interface-change INTO ls_change.
ls_change-parameter. =
?= cl_abap_datadescr=>describe_by_name( p_name = ls_change-structure ).
APPEND ls_components TO lt_components.
ENDLOOP.
"表参数
LOOP AT ls_interface-tables INTO ls_table.
ls_table-parameter. =
lo_datadescr ?= cl_abap_datadescr=>describe_by_name( p_name = ls_table-structure ).
"根据行结构创建表结构
CALL METHOD cl_abap_tabledescr=>create
EXPORTING
p_line_type = lo_datadescr
RECEIVING
p_result = ls_components-type.
APPEND ls_components TO lt_components.
ENDLOOP.
"创建出参结构
CALL METHOD cl_abap_structdescr=>create
EXPORTING
p_components = lt_components
RECEIVING
p_result = lo_struct.
CREATE DATA lo_data_out TYPE HANDLE lo_struct.
ASSIGN lo_data_out->* TO <fs_data_out>.
LOOP AT lt_param INTO ls_param WHERE kind <> abap_func_exporting.
ASSIGN COMPONENT ls_param-name OF STRUCTURE <fs_data_out> TO <fs_value>.
CHECK sy-subrc = 0.
ASSIGN ls_param-value->* TO FIELD-SYMBOL(<fs_val>).
<fs_val>. =
ENDLOOP.
"出参序列化
lv_json_out = /ui2/cl_json=>serialize( data = lo_data_out ).
cl_demo_output=>display_json( lv_json_out ).
ENDIF.
BREAK-POINT.
04
重点代码介绍
cl_fb_function_utility=>meth_get_interface(
EXPORTING
im_name = cns_name
IMPORTING
ex_interface = ls_interface ).
2.根据结构名获取组件类型
ls_components-type ?= cl_abap_datadescr=>describe_by_name( p_name = ls_change-structure ).
3.根据行结构类型创建表类型
CALL METHOD cl_abap_tabledescr=>create
EXPORTING
p_line_type = lo_datadescr
RECEIVING
p_result = ls_components-type.
4.根据组件内表创建动态结构类型
CALL METHOD cl_abap_structdescr=>create
EXPORTING
p_components = lt_components
RECEIVING
p_result = lo_struct.
5.根据动态结构类型创建对象引用,并分配给字段符号
CREATE DATA lo_data_in TYPE HANDLE lo_struct.
ASSIGN lo_data_in->* TO <fs_data_in>.
6.动态调用Function
CALL FUNCTION cns_name
PARAMETER-TABLE lt_param
EXCEPTION-TABLE lt_except.
7.JSON序列化和反序列化
CALL METHOD /ui2/cl_json=>deserialize
EXPORTING
json = lv_json_in
CHANGING
data = lo_data_in.
lv_json_out = /ui2/cl_json=>serialize( data = lo_data_out ).
05
输出结果
lv_json_in = '{"IV_VALUE":"JAVA","IT_INPUT":[{"WERKS":"1000"},{"WERKS":"2000"}]}'.
温馨提示
如果你喜欢本文,请分享给有需要的朋友,想要获得更多信息,请关注我,若有问题以及建议,请在文末留言或者私信。