调用需求
现在SAP系统需要调用.net服务器中的接口,接口是http
这样式的. 但是第三方给到我们的是两个http
接口,一个是用来登陆,另一个是用来获取具体的数据.
必须先使用登陆接口的http
然后再使用另一个http
接口获取举提数据.
postman测试可以可以正常获取到数据,但也需要在postman中先执行登陆的http
接口. 因为postman这个测试工具他会把这两个域名相同的http
接口的cookies
进行关联,因此登陆之后可以直接再获取数据.
但在abap代码中并不可以自动进行关联cookies
所以需要我们手动进行关联.
大致原理
我们需要创建两个客户端来进行连接.net服务器,A客户端用来登陆;B客户端用来获取数据.
如果说只是单纯的执行完A客户端再执行B客户端这样是不行的.所以我们需要获取到A客户端中的cookies
把他给到B客户端,这样B客户端就会拿着cookis
作为登陆过后的标识进行获取数据.
这里我们会用到工厂对象接口和工厂流
代码解析
我的这个登陆是POST
的请求,用户名,密码及标识是放在body
上的,
设置body参数方法 set_cdata( )
设置请求头,方法set_header_field( )
设置请求的方法,set_method( )
A客户端
cl_http_client=>create_by_url(
EXPORTING
url = login "登陆的http接口
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
DATA var_string TYPE string VALUE '{"u":"用户名","p":"密码","cn":"系统标识"}'.
lo_http_client->request->set_cdata( data = var_string ).
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'Content-Type'
value = 'application/JSON; charset=utf-8'.
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'x-csrf-token'
value = 'Fetch'.
CALL METHOD lo_http_client->request->set_method( 'POST' ).
"发送
lo_http_client->send(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2 ).
"接收
lo_http_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3 ).
简单的来说就是把登陆成功之后的cookies
放到工厂中去,通过工程流在再把它给到B客户端
lv_result = lo_http_client->response->get_cdata( ).
lv_csrf = lo_http_client->response->get_header_field( name = 'x-csrf-token' ). "获取token
lo_http_client->response->get_cookies( CHANGING cookies = lt_cookies ). "获取cookies
lo_ixml = cl_ixml=>create( ).
lo_streamfactory = lo_ixml->create_stream_factory( ).
lo_istream = lo_streamfactory->create_istream_string(
lv_result ).
lo_document = lo_ixml->create_document( ).
lo_parser = lo_ixml->create_parser(
stream_factory = lo_streamfactory
istream = lo_istream
document = lo_document ).
lo_parser->parse( ).
CALL METHOD lo_http_client->close.
B客户端
和A客户端一样的操作,只是比他多了一个请求头,多的就是咱们获取到的cookies
作为请求头,然后再把这个cookies
给到B客户端
设置cookie方法;set_cookie( )
CALL METHOD lo_http_client1->request->set_header_field
EXPORTING
name = 'x-csrf-token'
value = lv_csrf.
"设置cookies
LOOP AT lt_cookies ASSIGNING FIELD-SYMBOL(<cookie>).
lo_http_client1->request->set_cookie( name = <cookie>-name
value = <cookie>-value ).
ENDLOOP.
根据你的需求来发送你的请求参数,JSON
格式的,也是在body中发送的,也是post的请求.
lv_json = '你要发送的请求参数'
len = strlen( lv_json ) . "请求参数的长度
CALL METHOD lo_http_client1->request->set_cdata
EXPORTING
data = lv_json
offset = 0
length = len.
其他就没什么了.
cl_demo_output=>display( lv_result ).
总结
这个我们用到了工厂,我的个人理解是:我们把两个客户端所建立的连接放到同一个工厂中去,由工厂进行管理,在工厂中的数据是共享的,可以相互使用.
源代码
以下源码仅供参考
*&---------------------------------------------------------------------*
*& Report Z_HTTP_DEMO_004
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT z_http_demo_004.
DATA: lo_http_client TYPE REF TO if_http_client, "第一个cl_http_client 用于登陆
lo_http_client1 TYPE REF TO if_http_client, "第二个cl_http_client 用于获取数据
login TYPE string,
lv_result TYPE string,
lv_csrf TYPE string,
lt_cookies TYPE tihttpcki,
lo_ixml TYPE REF TO if_ixml,
lo_streamfactory TYPE REF TO if_ixml_stream_factory,
lo_istream TYPE REF TO if_ixml_istream,
lo_document TYPE REF TO if_ixml_document,
lo_parser TYPE REF TO if_ixml_parser.
login = 'http://login'.
"第一个cl_http_client使用post获取token和cookies
cl_http_client=>create_by_url(
EXPORTING
url = login
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
DATA var_string TYPE string VALUE '{"u":"用户名","p":"密码","cn":"系统标识"}'.
lo_http_client->request->set_cdata( data = var_string ).
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'Content-Type'
value = 'application/JSON; charset=utf-8'.
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'x-csrf-token'
value = 'Fetch'.
CALL METHOD lo_http_client->request->set_method( 'POST' ).
lo_http_client->send(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2 ).
lo_http_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3 ).
CLEAR lv_result .
lv_result = lo_http_client->response->get_cdata( ).
lv_csrf = lo_http_client->response->get_header_field( name = 'x-csrf-token' ). "获取token
lo_http_client->response->get_cookies( CHANGING cookies = lt_cookies ). "获取cookies
lo_ixml = cl_ixml=>create( ).
lo_streamfactory = lo_ixml->create_stream_factory( ).
lo_istream = lo_streamfactory->create_istream_string(
lv_result ).
lo_document = lo_ixml->create_document( ).
lo_parser = lo_ixml->create_parser(
stream_factory = lo_streamfactory
istream = lo_istream
document = lo_document ).
lo_parser->parse( ).
CALL METHOD lo_http_client->close.
"第二个cl_http_client用前面获取的token和cookies来执行POST
cl_http_client=>create_by_url(
EXPORTING
url = 'http'
IMPORTING
client = lo_http_client1
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
CALL METHOD lo_http_client1->request->set_header_field
EXPORTING
name = 'Content-Type'
value = 'application/JSON; charset=utf-8'.
CALL METHOD lo_http_client1->request->set_header_field
EXPORTING
name = 'x-csrf-token'
value = lv_csrf. "使用第一个cl_http_clien获取的token
"设置cookies
LOOP AT lt_cookies ASSIGNING FIELD-SYMBOL(<cookie>).
lo_http_client1->request->set_cookie( name = <cookie>-name
value = <cookie>-value ).
ENDLOOP.
CALL METHOD lo_http_client1->request->set_method( 'POST' ).
DATA lv_json TYPE string.
DATA: len TYPE i .
lv_json = xxxxxxxx
len = strlen( lv_json ) .
CALL METHOD lo_http_client1->request->set_cdata
EXPORTING
data = lv_json
offset = 0
length = len.
*发送请求
lo_http_client1->send(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2 ).
*接收返回参数
lo_http_client1->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3 ).
CLEAR lv_result .
lv_result = lo_http_client1->response->get_cdata( ). "获取接收参数
lo_ixml = cl_ixml=>create( ).
lo_streamfactory = lo_ixml->create_stream_factory( ).
lo_istream = lo_streamfactory->create_istream_string(
lv_result ).
lo_document = lo_ixml->create_document( ).
lo_parser = lo_ixml->create_parser(
stream_factory = lo_streamfactory
istream = lo_istream
document = lo_document ).
lo_parser->parse( ).
CALL METHOD lo_http_client1->close.
cl_demo_output=>display( lv_result ).