最近的项目中,接口较多,而Webservice技术是主要实现方式之一。下面以项目中的一个具体实例来体验一下基于PI的Webservice发布。
业务场景
SAP系统实时接收一个外围接口系统(基于Web的电子商务平台)回传的数据。
技术分析
由于同步要求较高,数据量偏小,采用Webservice实现较为合理。
实例演示
创建好自建表,用于接收回传的数据:
TC: SPROXY根据集成组在PI配置的服务名创建Service Interface
在实现类中,根据传入的XML字符串,解析后更新到自建表:
data: ls_field_data like zmmjyh_cdif,
lt_field_data like table of ls_field_data,
ls_zmmjyh_ht_0007 like zmmjyh_ht_0007,
lt_zmmjyh_ht_0007 like table of ls_zmmjyh_ht_0007,
l_retcode type i,
l_fieldname type string,
l_float type f.
field-symbols: <fs_fieldname> type any,
<fs_fieldvalue> type any.
"解析XML数据到通用内表
type-pools: ixml.
types: begin of t_xml_line ,
data(256) type x,
end of t_xml_line.
data: l_ixml type ref to if_ixml,
l_streamfactory type ref to if_ixml_stream_factory,
l_parser type ref to if_ixml_parser,
l_istream type ref to if_ixml_istream,
l_document type ref to if_ixml_document,
l_node type ref to if_ixml_node,
l_xmldata type string.
data: l_elem type ref to if_ixml_element,
l_root_node type ref to if_ixml_node,
l_next_node type ref to if_ixml_node,
l_name type string,
l_iterator type ref to if_ixml_node_iterator.
data: l_xml_table type table of t_xml_line,
l_xml_line type t_xml_line,
l_xml_table_size type i.
* Creating the main iXML factory
l_ixml = cl_ixml=>create( ).
* Creating a stream factorya
l_streamfactory = l_ixml->create_stream_factory( ).
l_istream = l_streamfactory->create_istream_string( string = input ).
* Creating a document
l_document = l_ixml->create_document( ).
* Create a Parser
l_parser = l_ixml->create_parser( stream_factory = l_streamfactory
istream = l_istream
document = l_document ).
* Parse the stream
if l_parser->parse( ) ne 0.
l_retcode = 0.
return .
endif.
* Process the document
if l_parser->is_dom_generating( ) eq 'X'.
perform process_dom tables lt_field_data using l_document .
endif.
*&--------------------------------------------------------------------*
*& Form process_dom
*&--------------------------------------------------------------------*
form process_dom tables p_i_zxml structure zmmjyh_cdif
using document type ref to if_ixml_document .
data: node type ref to if_ixml_node,
iterator type ref to if_ixml_node_iterator,
nodemap type ref to if_ixml_named_node_map,
node_parent type ref to if_ixml_node,
attr type ref to if_ixml_node,
name type string,
name1 type string,
prefix type string,
value type string,
indent type i,
count type i,
index type i.
node ?= document.
check not node is initial.
if node is initial.
exit.
endif.
* create a node iterator
iterator = node->create_iterator( ).
* get current node
node = iterator->get_next( ).
* loop over all nodes
while not node is initial.
indent = node->get_height( ) * 2.
indent = indent + 20.
case node->get_type( ).
when if_ixml_node=>co_node_element.
* element node
name = node->get_name( ).
nodemap = node->get_attributes( ).
if not nodemap is initial.
* attributes
count = nodemap->get_length( ).
do count times.
index = sy-index - 1.
attr = nodemap->get_item( index ).
name = attr->get_name( ).
prefix = attr->get_namespace_prefix( ).
value = attr->get_value( ).
"记录字段名、字段值
p_i_zxml-fieldname = name .
p_i_zxml-fieldvalue = value .
append p_i_zxml .
enddo.
endif.
when if_ixml_node=>co_node_text or
if_ixml_node=>co_node_cdata_section.
* text node
value = node->get_value( ).
node_parent = node->get_parent( ).
name1 = node_parent->get_name( ).
"记录字段名、字段值
p_i_zxml-fieldname = name1 .
p_i_zxml-fieldvalue = value .
append p_i_zxml .
endcase.
node = iterator->get_next( ).
endwhile.
endform. "process_dom
"准备数据到数据库更新内表
loop at lt_field_data into ls_field_data.
clear l_fieldname.
assign ls_field_data-fieldvalue to <fs_fieldvalue>.
concatenate 'LS_ZMMJYH_HT_0007-' ls_field_data-fieldname into l_fieldname.
assign (l_fieldname) to <fs_fieldname>.
if <fs_fieldname> is assigned.
if ls_field_data-fieldname = 'CONTRAMOUNTNUM'
or ls_field_data-fieldname = 'APPLYAMOUNT'.
"金额字段中科学计数法的处理
clear l_float.
l_float = <fs_fieldvalue>.
<fs_fieldname> = l_float.
else.
<fs_fieldname> = <fs_fieldvalue>.
endif.
else.
it_return-zresult = '0'.
it_return-description = '程序异常,字段名不匹配!'.
append it_return.
return.
endif.
"到达一条数据末尾
if ls_field_data-fieldname = 'PREPAYID'.
append ls_zmmjyh_ht_0007 to lt_zmmjyh_ht_0007.
clear ls_zmmjyh_ht_0007.
endif.
endloop.
"更新到自建表
if lines( lt_zmmjyh_ht_0007 ) > 0 .
modify zmmjyh_ht_0007 from table lt_zmmjyh_ht_0007.
if sy-subrc = 0.
commit work and wait.
it_return-zresult = '1'.
it_return-description = '回传成功!'.
append it_return.
else.
rollback work.
it_return-zresult = '0'.
it_return-description = '回传失败,数据库更新异常!'.
append it_return.
endif.
else.
it_return-zresult = '0'.
it_return-description = '无数据可传输!'.
append it_return.
endif.
把结果回传给外围系统,先创建好Transformation
然后把返回值封装成XML串:
data:l_xstr type xstring.
call transformation zmmjyhmesgjdzsw
source root = it_return[]
* RESULT XML output
result xml l_xstr
options xml_header = 'no' .
types: begin of ty_bin,
bin_data(1024) type x,
end of ty_bin.
data:lt_bin type table of ty_bin."文件二进制内表
data:l_len type i.
check input is not initial.
call function 'SCMS_XSTRING_TO_BINARY'
exporting
buffer = l_xstr
* APPEND_TO_TABLE = ' '
importing
output_length = l_len
tables
binary_tab = lt_bin
.
call function 'SCMS_BINARY_TO_STRING'
exporting
input_length = l_len
* FIRST_LINE = 0
* LAST_LINE = 0
* MIMETYPE = ' '
* ENCODING =
importing
text_buffer = output-zmmjyht010response-output
* OUTPUT_LENGTH =
tables
binary_tab = lt_bin
* EXCEPTIONS
* FAILED = 1
* OTHERS = 2
.
if sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
endif.
由于是基于PI创建的,此时的Webservice还没有注册,TC:SOAMANAGER
进入single serviceadministration,搜索刚才创建的webservice:Zmmjyht010,并apply selection
点选Configurations标签,创建服务:
记得勾选中 User ID/Password
点击 show wsdl options,并把 WSDL Format 设置为standard,然后点选Display selectedBinding's WSDL URL,
在右边会得到WSDL的URL
在SICF中,找到服务 Zmmjyht010,在登录数据里,把过程数据改为 “标准”,这是为了跳过WSDL的安全策略。
最后,然后把此WSDL的URL给到外围系统的开发人员就可以了。