Axis2/C 基础入门
Axis2/C是一个用C语言实现的Web Service引擎。
Axis2/C基于 Axis2架构,支持 SOAP1.1和 SOAP1.2协议,并且支持 RESTful风格的Web Service。基于Axis2/C的Web Service可以同时暴露为SOAP和RESTful风格的服务。
最近研究了一下Axis2/C,这篇文章详述了如何利用Axis2/C发布一个Web Service,并通过SOAP访问这个Web Service。
一、Axis2/C的下载和安装
1、可以从Axis2/C的官方网站下载到最新的Axis2/C发布包: Axis2/C下载
2、解压axis2c-bin-1.6.0-win32.zip,并在系统的环境变量中添加AXIS2_HOME并指向Axis2/C的解压目录,这样可以确保后续编译过程中可以找到Axis2/C的依赖项;
3、在系统环境变量中找到Path项,编辑该项,在它的最开始加入C:\VS8\Common7\IDE,并以分号分隔,以此保证编译后的客户端程序可以顺利找到依赖项;
4、在Path的结尾添加%AXIS2_HOME%\lib,确保编译器可以找到Axis2/C的依赖项;
二、构建和发布服务
5、新建CPP文件,命名为:hello_svc.c,并加入如下代码:
1
#include
"
stdafx.h
"
2
3
#include
<
axis2_svc_skeleton.h
>
4
#include
<
axutil_log_default.h
>
5
#include
<
axutil_error_default.h
>
6
#include
<
axutil_array_list.h
>
7
#include
<
axiom_text.h
>
8
#include
<
axiom_node.h
>
9
#include
<
axiom_element.h
>
10
#include
<
stdio.h
>
11
12
axiom_node_t
*
axis2_hello_greet(
const
axutil_env_t
*
env, axiom_node_t
*
node);
13
int
AXIS2_CALL hello_free(axis2_svc_skeleton_t
*
svc_skeleton,
const
axutil_env_t
*
env);
14
axiom_node_t
*
AXIS2_CALL hello_invoke(axis2_svc_skeleton_t
*
svc_skeleton,
const
axutil_env_t
*
env, axiom_node_t
*
node, axis2_msg_ctx_t
*
msg_ctx);
15
int
AXIS2_CALL hello_init(axis2_svc_skeleton_t
*
svc_skeleton,
const
axutil_env_t
*
env);
16
axiom_node_t
*
AXIS2_CALL hello_on_fault(axis2_svc_skeleton_t
*
svc_skeli,
const
axutil_env_t
*
env, axiom_node_t
*
node);
17
axiom_node_t
*
build_greeting_response(
const
axutil_env_t
*
env, axis2_char_t
*
greeting);
18
19
axiom_node_t
*
axis2_hello_greet(
const
axutil_env_t
*
env, axiom_node_t
*
node)
20
{
21
axiom_node_t
*
client_greeting_node
=
NULL;
22
axiom_node_t
*
return_node
=
NULL;
23
AXIS2_ENV_CHECK(env, NULL);
24
if
(node)
25
{
26
client_greeting_node
=
axiom_node_get_first_child(node, env);
27
if
(client_greeting_node
&&
axiom_node_get_node_type(client_greeting_node, env)
==
AXIOM_TEXT)
28
{
29
axiom_text_t
*
greeting
=
(axiom_text_t
*
)axiom_node_get_data_element(client_greeting_node, env);
30
if
(greeting
&&
axiom_text_get_value(greeting , env))
31
{
32
const
axis2_char_t
*
greeting_str
=
axiom_text_get_value(greeting, env);
33
printf(
"
Client greeted saying \
"
%
s\
"
\n
"
, greeting_str);
34
return_node
=
build_greeting_response(env,
"
Hello Client!
"
);
35
}
36
}
37
}
38
else
39
{
40
AXIS2_ERROR_SET(env
->
error, AXIS2_ERROR_SVC_SKEL_INVALID_XML_FORMAT_IN_REQUEST, AXIS2_FAILURE);
41
printf(
"
ERROR: invalid XML in request\n
"
);
42
return_node
=
build_greeting_response(env,
"
Client! Who are you?
"
);
43
}
44
return
return_node;
45
}
46
47
48
49
axiom_node_t
*
build_greeting_response(
const
axutil_env_t
*
env, axis2_char_t
*
greeting)
50
{
51
axiom_node_t
*
greeting_om_node
=
NULL;
52
axiom_element_t
*
greeting_om_ele
=
NULL;
53
greeting_om_ele
=
axiom_element_create(env, NULL,
"
greetResponse
"
, NULL,
&
greeting_om_node);
54
axiom_element_set_text(greeting_om_ele, env, greeting, greeting_om_node);
55
return
greeting_om_node;
56
}
57
58
static
const
axis2_svc_skeleton_ops_t hello_svc_skeleton_ops_var
=
{
59
hello_init,
60
hello_invoke,
61
hello_on_fault,
62
hello_free
63
};
64
65
axis2_svc_skeleton_t
*
axis2_hello_create(
const
axutil_env_t
*
env)
66
{
67
axis2_svc_skeleton_t
*
svc_skeleton
=
NULL;
68
svc_skeleton
=
(axis2_svc_skeleton_t
*
) AXIS2_MALLOC(env
->
allocator,
sizeof
(axis2_svc_skeleton_t));
69
svc_skeleton
->
ops
=
&
hello_svc_skeleton_ops_var;
70
svc_skeleton
->
func_array
=
NULL;
71
return
svc_skeleton;
72
}
73
74
int
AXIS2_CALL hello_init(axis2_svc_skeleton_t
*
svc_skeleton,
const
axutil_env_t
*
env)
75
{
76
svc_skeleton
->
func_array
=
axutil_array_list_create(env,
0
);
77
axutil_array_list_add(svc_skeleton
->
func_array, env,
"
helloString
"
);
78
return
AXIS2_SUCCESS;
79
}
80
81
82
83
axiom_node_t
*
AXIS2_CALL hello_invoke(axis2_svc_skeleton_t
*
svc_skeleton,
const
axutil_env_t
*
env, axiom_node_t
*
node, axis2_msg_ctx_t
*
msg_ctx)
84
{
85
return
axis2_hello_greet(env, node);
86
}
87
88
axiom_node_t
*
AXIS2_CALL hello_on_fault(axis2_svc_skeleton_t
*
svc_skeli,
const
axutil_env_t
*
env, axiom_node_t
*
node)
89
{
90
axiom_node_t
*
error_node
=
NULL;
91
axiom_node_t
*
text_node
=
NULL;
92
axiom_element_t
*
error_ele
=
NULL;
93
error_ele
=
axiom_element_create(env, node,
"
EchoServiceError
"
, NULL,
94
&
error_node);
95
axiom_element_set_text(error_ele, env,
"
Echo service failed
"
,
96
text_node);
97
return
error_node;
98
}
99
100
101
102
int
AXIS2_CALL hello_free(axis2_svc_skeleton_t
*
svc_skeleton,
103
const
axutil_env_t
*
env)
104
{
105
if
(svc_skeleton
->
func_array)
106
{
107
axutil_array_list_free(svc_skeleton
->
func_array, env);
108
svc_skeleton
->
func_array
=
NULL;
109
}
110
111
if
(svc_skeleton)
112
{
113
AXIS2_FREE(env
->
allocator, svc_skeleton);
114
svc_skeleton
=
NULL;
115
}
116
return
AXIS2_SUCCESS;
117
}
118
119
AXIS2_EXPORT
int
axis2_get_instance(axis2_svc_skeleton_t
**
inst,
const
axutil_env_t
*
env)
120
{
121
*
inst
=
axis2_hello_create(env);
122
if
(
!
(
*
inst))
123
{
124
return
AXIS2_FAILURE;
125
}
126
return
AXIS2_SUCCESS;
127
}
128
129
130
131
AXIS2_EXPORT
int
axis2_remove_instance(axis2_svc_skeleton_t
*
inst,
const
axutil_env_t
*
env)
132
{
133
axis2_status_t status
=
AXIS2_FAILURE;
134
if
(inst)
135
{
136
status
=
AXIS2_SVC_SKELETON_FREE(inst, env);
137
}
138
return
status;
139
}
140
6、编译上述代码,在命令行运行如下编译命令:
$ C:\VS8\VC\bin\cl.exe
/
D
"
WIN32
"
/
D
"
_WINDOWS
"
/
D
"
_MBCS
"
/
D
"
AXIS2_DECLARE_EXPORT
"
/
D
"
AXIS2_SVR_MULTI_THREADED
"
/
w
/
nologo
/
I
%
AXIS2_HOME%
\include
/
I C:\\VS8\\VC\\include
/
c hello_svc.c
7、链接生成的中间对象,并产生DLL,运行命令如下:
$ C:\VS8\VC\bin\link.exe
/
nologo
/
LIBPATH:
%
AXIS2_HOME%
\lib
/
LIBPATH:C:\\VS8\\VC\\lib axutil.lib axiom.lib axis2_parser.lib axis2_engine.lib
/
DLL
/
OUT:hello.dll
*
.obj
8、在
%AXIS2_HOME%\services下创建目录hello,将步骤7产生的hello.dll拷贝到其中,并创建服务描述文件services.xml,并插入如下内容:
1
<?
xml version="1.0" encoding="utf-8"
?>
2
<
service
name
="hello"
>
3
<
parameter
name
="ServiceClass"
locked
="xsd:false"
>
hello
</
parameter
>
4
<
description
>
5
Quick start guide hello service sample.
6
</
description
>
7
<
operation
name
="greet"
>
8
<
parameter
name
="wsamapping"
>
http://ws.apache.org/axis2/c/samples/hello
</
parameter
>
9
</
operation
>
10
</
service
>
9、启动Axis2服务器,执行如下命令:
$ axis2_http_server
三、访问服务
10、在VS中创建项目Axis2Test,并在Axis2Test.cpp中插入这些代码:
1
#include
"
stdafx.h
"
2
3
#include
<
stdio.h
>
4
#include
<
axiom.h
>
5
#include
<
axis2_util.h
>
6
#include
<
axiom_soap.h
>
7
#include
<
axis2_client.h
>
8
9
axiom_node_t
*
build_om_request(
const
axutil_env_t
*
env);
10
const
axis2_char_t
*
process_om_response(
const
axutil_env_t
*
env, axiom_node_t
*
node);
11
12
int
_tmain(
int
argc,
char
**
argv)
13
{
14
const
axutil_env_t
*
env
=
NULL;
15
const
axis2_char_t
*
address
=
NULL;
16
axis2_endpoint_ref_t
*
endpoint_ref
=
NULL;
17
axis2_options_t
*
options
=
NULL;
18
const
axis2_char_t
*
client_home
=
NULL;
19
axis2_svc_client_t
*
svc_client
=
NULL;
20
axiom_node_t
*
payload
=
NULL;
21
axiom_node_t
*
ret_node
=
NULL;
22
23
env
=
axutil_env_create_all(
"
hello_client.log
"
, AXIS2_LOG_LEVEL_TRACE);
24
options
=
axis2_options_create(env);
25
address
=
"
http://localhost:9090/axis2/services/hello
"
;
26
27
if
(argc
>
1
)
28
address
=
argv[
1
];
29
30
if
(axutil_strcmp(address,
"
-h
"
)
==
0
)
31
{
32
printf(
"
Usage : %s [endpoint_url]\n
"
, argv[
0
]);
33
printf(
"
use -h for help\n
"
);
34
return
0
;
35
}
36
37
printf(
"
Using endpoint : %s\n
"
, address);
38
endpoint_ref
=
axis2_endpoint_ref_create(env, address);
39
axis2_options_set_to(options, env, endpoint_ref);
40
axis2_options_set_action(options, env,
"
http://ws.apache.org/axis2/c/samples/hello
"
);
41
42
client_home
=
"
E:\\mengli\\axis2c-bin-1.6.0-win32
"
;
//
AXIS2_GETENV("AXIS2C_HOME");
43
if
(
!
client_home
&&
!
strcmp(client_home,
""
))
44
client_home
=
"
../..
"
;
45
46
svc_client
=
axis2_svc_client_create(env, client_home);
47
if
(
!
svc_client)
48
{
49
printf(
"
Error creating service client\n
"
);
50
AXIS2_LOG_ERROR(env
->
log, AXIS2_LOG_SI,
"
Stub invoke FAILED: Error code:
"
51
"
%d :: %s
"
, env
->
error
->
error_number,
52
AXIS2_ERROR_GET_MESSAGE(env
->
error));
53
return
-
1
;
54
}
55
56
axis2_svc_client_set_options(svc_client, env, options);
57
payload
=
build_om_request(env);
58
ret_node
=
axis2_svc_client_send_receive(svc_client, env, payload);
59
60
if
(ret_node)
61
{
62
const
axis2_char_t
*
greeting
=
process_om_response(env, ret_node);
63
if
(greeting)
64
printf(
"
\nReceived greeting: \
"
%
s\
"
from service\n
"
, greeting);
65
66
axiom_node_free_tree(ret_node, env);
67
ret_node
=
NULL;
68
}
69
else
70
{
71
AXIS2_LOG_ERROR(env
->
log, AXIS2_LOG_SI,
"
Stub invoke FAILED: Error code:
"
72
"
%d :: %s
"
, env
->
error
->
error_number,
73
AXIS2_ERROR_GET_MESSAGE(env
->
error));
74
printf(
"
hello client invoke FAILED!\n
"
);
75
}
76
77
if
(svc_client)
78
{
79
axis2_svc_client_free(svc_client, env);
80
svc_client
=
NULL;
81
}
82
83
if
(env)
84
{
85
axutil_env_free((axutil_env_t
*
) env);
86
env
=
NULL;
87
}
88
89
return
0
;
90
91
}
92
93
axiom_node_t
*
94
build_om_request(
const
axutil_env_t
*
env)
95
{
96
axiom_node_t
*
greet_om_node
=
NULL;
97
axiom_element_t
*
greet_om_ele
=
NULL;
98
99
greet_om_ele
=
axiom_element_create(env, NULL,
"
greet
"
, NULL,
&
greet_om_node);
100
axiom_element_set_text(greet_om_ele, env,
"
Hello Server!
"
, greet_om_node);
101
102
return
greet_om_node;
103
}
104
105
106
107
const
axis2_char_t
*
108
process_om_response(
const
axutil_env_t
*
env,
109
axiom_node_t
*
node)
110
{
111
axiom_node_t
*
service_greeting_node
=
NULL;
112
axiom_node_t
*
return_node
=
NULL;
113
114
if
(node)
115
{
116
service_greeting_node
=
axiom_node_get_first_child(node, env);
117
118
if
(service_greeting_node
&&
119
axiom_node_get_node_type(service_greeting_node, env)
==
AXIOM_TEXT)
120
{
121
axiom_text_t
*
greeting
=
(axiom_text_t
*
)axiom_node_get_data_element(service_greeting_node, env);
122
if
(greeting
&&
axiom_text_get_value(greeting , env))
123
{
124
return
axiom_text_get_value(greeting, env);
125
}
126
}
127
}
128
129
return
NULL;
130
}
11、编译并执行该程序,会向远程服务发送字符串
Hello Service!,并得到响应
Hello Client!