【SAP】SAP restful http 接口集中管理发布(SICF)
引言
最近在项目上有做一些restful接口的需求,其中涉及到多个外围系统,就想着如何通过只发布一个服务,让个外围系统传入不同的报文,来决定动态的调用不同的业务处理程序,于是就有了这篇博客.
实现过程
跟外围系统定义报文格式的时候,确定了报文的总体格式,要求不管什么接口,总体格式不变。结构如下:
{
"HEAD": {
"TARGET_SYS": "SAP",
"INTF_ID": "INT_FI001",
"SOURCE_SYS": "OA"
},
"DATA":""
}
其中定义了两个固定格式,head与data,head中包含了接口的目标系统、源系统以及接口编号,data部分用于传输业务数据,结构与业务字段需根据实际确定。
注意,由于在json转abap对象时没有指定具体数据类型,所以由前端系统将所有数据转成字符串类型传输,避免在sap将小数转换成浮点数。
原始数据

转换后数据

确定好报文格式后,剩下来的只需要在SAP内处理了。代码如下:
METHOD if_rest_resource~post.
DATA lo_object TYPE REF TO object.
DATA lo_infter TYPE REF TO zif_interface_http.
DATA lv_clname TYPE c LENGTH 30.
DATA ls_head TYPE zsifheadinfo.
DATA ls_return TYPE bapiret2.
DATA:BEGIN OF ls_data,
head TYPE zsifheadinfo,
data TYPE REF TO data,
END OF ls_data.
" 获取报文。
DATA(lv_json) = mo_request->get_entity( )->get_string_data( ).
/ui2/cl_json=>deserialize( EXPORTING json = lv_json
CHANGING data = ls_data ).
ASSIGN COMPONENT 'HEAD' OF STRUCTURE ls_data TO FIELD-SYMBOL(<fs_head>).
IF sy-subrc <> 0 OR <fs_head> IS NOT ASSIGNED OR <fs_head> IS INITIAL.
ls_return-message = '数据解析异常:缺少HEAD数据'.
return_error( ls_return ).
RETURN.
ELSE.
MOVE-CORRESPONDING <fs_head> TO ls_head.
ENDIF.
ASSIGN COMPONENT 'DATA' OF STRUCTURE ls_data TO FIELD-SYMBOL(<fs_data>).
IF sy-subrc <> 0 OR <fs_data> IS NOT ASSIGNED OR <fs_data> IS INITIAL.
ls_return-message = '数据解析异常:缺少DATA数据'.
return_error( ls_return ).
RETURN.
ENDIF.
" 根据接口id确定业务实现类
SELECT SINGLE object_name INTO lv_clname
FROM ztiftable
WHERE intf_id = ls_head-intf_id
AND zactive = 'X'
AND zinout = 'I'.
TRY.
CREATE OBJECT lo_object TYPE (lv_clname)
EXPORTING iv_head = ls_head
iv_uuid = cl_system_uuid=>create_uuid_c36_static( ).
CATCH cx_uuid_error INTO DATA(lo_uuid_error).
ls_return-message = lo_uuid_error->get_text( ).
return_error( ls_return ).
RETURN.
CATCH cx_sy_create_object_error INTO DATA(lo_object_error).
ls_return-message = lo_object_error->get_text( ).
return_error( ls_return ).
RETURN.
CATCH cx_sy_dyn_call_illegal_method INTO DATA(lo_illegal_method).
ls_return-message = lo_illegal_method->get_text( ).
return_error( ls_return ).
RETURN.
CATCH cx_sy_dyn_call_illegal_type INTO DATA(lo_illegal_type).
ls_return-message = lo_illegal_type->get_text( ).
return_error( ls_return ).
RETURN.
CATCH cx_sy_dyn_call_param_not_found INTO DATA(lo_param_not_found).
ls_return-message = lo_param_not_found->get_text( ).
return_error( ls_return ).
RETURN.
CATCH cx_root INTO DATA(lo_root).
ls_return-message = lo_root->get_text( ).
return_error( ls_return ).
RETURN.
ENDTRY.
IF lo_object IS INSTANCE OF zif_interface_http.
lo_infter ?= lo_object.
ENDIF.
IF lo_infter IS INITIAL.
ls_return-message = '实例未引用接口类(ZIF_INTERFACE_HTTP)'.
return_error( ls_return ).
RETURN.
ENDIF.
DATA re_data TYPE string.
DATA iv_data TYPE string.
iv_data = /ui2/cl_json=>serialize( <fs_data> ).
lo_infter->procrss_data( EXPORTING iv_data = iv_data
CHANGING re_data = re_data
re_return = ls_return ).
IF re_data IS NOT INITIAL.
mo_response->set_reason( 'ok' ).
mo_response->set_status( 200 ).
mo_response->create_entity( )->set_string_data( re_data ).
mo_response->create_entity( )->set_content_type( if_rest_media_type=>gc_appl_json ).
ELSE.
return_error( ls_return ).
ENDIF.
ENDMETHOD.
以上代码的大致内容就是,通过接口传入的报文,生成对应的abap内部类型,进一步将报文转换为内表或结构体,从而根据HEAD与DATA字段来将其拆分处理,HEAD为接口相关数据,DATA为业务数据。之后通过接口编号找到对应的类名,实例化出一个对应的对象,后面如果lo_object是zif_interface_http 接口的实例,则将其引用赋值给lo_infter变量,这样就可以利用lo_infter来调用zif_interface_http接口中定义的方法来进行业务处理,在处理之前将data数据执行了abap2json的转换,用于更方便传递内容。
接口 zif_interface_http 的方法如下:
INTERFACE zif_interface_http
PUBLIC.
METHODS procrss_data
IMPORTING iv_data TYPE string OPTIONAL
iv_uuid TYPE string OPTIONAL
CHANGING VALUE(re_data) TYPE string OPTIONAL
re_return TYPE bapiret2 OPTIONAL.
METHODS check_data
CHANGING VALUE(cs_return) TYPE bapiret2.
METHODS save_data
CHANGING VALUE(cs_return) TYPE bapiret2.
METHODS call_bapi
CHANGING VALUE(cs_return) TYPE bapiret2.
METHODS abap2json
IMPORTING iv_return TYPE bapiret2
RETURNING VALUE(ev_data) TYPE string.
METHODS json2data
IMPORTING iv_data TYPE string OPTIONAL
CHANGING VALUE(re_data) TYPE data.
METHODS lock_order
CHANGING VALUE(cs_return) TYPE bapiret2.
ENDINTERFACE.
配置表中的业务处理类只有一个实例构造方法,其他方法引用接口。代码如下
DATA lo_error TYPE REF TO cx_sy_dyn_call_illegal_method.
TRY.
zif_interface_http~json2data( EXPORTING iv_data = iv_data
CHANGING re_data = mt_data ).
zif_interface_http~check_data( CHANGING cs_return = re_return ).
zif_interface_http~lock_order( CHANGING cs_return = re_return ).
zif_interface_http~call_bapi( CHANGING cs_return = re_return ).
zif_interface_http~save_data( CHANGING cs_return = re_return ).
re_data = zif_interface_http~abap2json( iv_return = re_return ).
CATCH cx_sy_dyn_call_illegal_method INTO lo_error.
re_return-message = lo_error->if_message~get_text( ).
ENDTRY.
处理之后的响应报文由各不同的类传递出json对象,直接返回给发送方。
剩下的就是一个返回错误的方法,没什么好说的,返回一个400的报错.
PS:本博文的服务发布过程参考我的另一篇文章SAP 发布HTTP接口之完整的Restful 含( 含Token 验证)
更多推荐


所有评论(0)