Apache Axis2 / C是以C编程语言实现的Web服务引擎。 它基于可扩展和灵活的Axis2架构。 Apache Axis2 / C可用于提供和使用Web服务。 它的实现具有可移植性和嵌入能力,因此可以在其他软件中用作Web服务启用器。
Apache Axis2 / C支持SOAP 1.1和SOAP 1.2以及REST风格的WebService。 单个服务可以同时作为SOAP风格和REST风格服务公开。 它还内置了MTOM支持,可用于交换二进制数据。
部署方法:
- 下载安装Axis2/C(http://axis.apache.org/axis2/c/core/download.cgi)
- 设置环境变量AXIS2C_HOME,值为安装根目录
- 设置环境变量Path,添加%AXIS2C_HOME%\lib
- 下载libxml2、iconv、zlib、openssl(ftp://ftp.zlatkovic.com/libxml),将libxml2.dll、iconv.dll、zlib1.dll、libeay32.dll、ssleay32.dll拷贝到AXIS2C_HOME
- 测试:运行AXIS2C_HOME\bin\axis2_http_server.exe(此时通过浏览器访问 http://localhost:9090/axis2/services可看到Deployed Services页面),再在命令行中运行AXIS2C_HOME\samples\bin中可执行程序,可看到运行结果
使用Axis2/C快速编写并部署一个WebService:
- 编写hello_svc.c,代码如下:
#include <axis2_svc_skeleton.h> #include <axutil_log_default.h> #include <axutil_error_default.h> #include <axutil_array_list.h> #include <axiom_text.h> #include <axiom_node.h> #include <axiom_element.h> #include <stdio.h> axiom_node_t *axis2_hello_greet(const axutil_env_t *env, axiom_node_t *node); int AXIS2_CALL hello_free(axis2_svc_skeleton_t *svc_skeleton, const axutil_env_t *env); 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); int AXIS2_CALL hello_init(axis2_svc_skeleton_t *svc_skeleton, const axutil_env_t *env); axiom_node_t* AXIS2_CALL hello_on_fault(axis2_svc_skeleton_t *svc_skeli, const axutil_env_t *env, axiom_node_t *node); axiom_node_t * build_greeting_response(const axutil_env_t *env, axis2_char_t *greeting); axiom_node_t * axis2_hello_greet(const axutil_env_t *env, axiom_node_t *node) { axiom_node_t *client_greeting_node = NULL; axiom_node_t *return_node = NULL; AXIS2_ENV_CHECK(env, NULL); if (node) { client_greeting_node = axiom_node_get_first_child(node, env); if (client_greeting_node && axiom_node_get_node_type(client_greeting_node, env) == AXIOM_TEXT) { axiom_text_t *greeting = (axiom_text_t *)axiom_node_get_data_element(client_greeting_node, env); if (greeting && axiom_text_get_value(greeting , env)) { const axis2_char_t *greeting_str = axiom_text_get_value(greeting, env); printf("Client greeted saying \"%s\" \n", greeting_str); return_node = build_greeting_response(env, "Hello Client!"); } } } else { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SVC_SKEL_INVALID_XML_FORMAT_IN_REQUEST, AXIS2_FAILURE); printf("ERROR: invalid XML in request\n"); return_node = build_greeting_response(env, "Client! Who are you?"); } return return_node; } axiom_node_t * build_greeting_response(const axutil_env_t *env, axis2_char_t *greeting) { axiom_node_t* greeting_om_node = NULL; axiom_element_t * greeting_om_ele = NULL; greeting_om_ele = axiom_element_create(env, NULL, "greetResponse", NULL, &greeting_om_node); axiom_element_set_text(greeting_om_ele, env, greeting, greeting_om_node); return greeting_om_node; } static const axis2_svc_skeleton_ops_t hello_svc_skeleton_ops_var = { hello_init, hello_invoke, hello_on_fault, hello_free }; axis2_svc_skeleton_t * axis2_hello_create(const axutil_env_t *env) { axis2_svc_skeleton_t *svc_skeleton = NULL; svc_skeleton = AXIS2_MALLOC(env->allocator, sizeof(axis2_svc_skeleton_t)); svc_skeleton->ops = &hello_svc_skeleton_ops_var; svc_skeleton->func_array = NULL; return svc_skeleton; } int AXIS2_CALL hello_init(axis2_svc_skeleton_t *svc_skeleton, const axutil_env_t *env) { svc_skeleton->func_array = axutil_array_list_create(env, 0); axutil_array_list_add(svc_skeleton->func_array, env, "helloString"); return AXIS2_SUCCESS; } 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) { return axis2_hello_greet(env, node); } axiom_node_t* AXIS2_CALL hello_on_fault(axis2_svc_skeleton_t *svc_skeli, const axutil_env_t *env, axiom_node_t *node) { axiom_node_t *error_node = NULL; axiom_node_t* text_node = NULL; axiom_element_t *error_ele = NULL; error_ele = axiom_element_create(env, node, "EchoServiceError", NULL, &error_node); axiom_element_set_text(error_ele, env, "Echo service failed ", text_node); return error_node; } int AXIS2_CALL hello_free(axis2_svc_skeleton_t *svc_skeleton, const axutil_env_t *env) { if (svc_skeleton->func_array) { axutil_array_list_free(svc_skeleton->func_array, env); svc_skeleton->func_array = NULL; } if (svc_skeleton) { AXIS2_FREE(env->allocator, svc_skeleton); svc_skeleton = NULL; } return AXIS2_SUCCESS; } AXIS2_EXPORT int axis2_get_instance(axis2_svc_skeleton_t **inst, const axutil_env_t *env) { *inst = axis2_hello_create(env); if (!(*inst)) { return AXIS2_FAILURE; } return AXIS2_SUCCESS; } AXIS2_EXPORT int axis2_remove_instance(axis2_svc_skeleton_t *inst, const axutil_env_t *env) { axis2_status_t status = AXIS2_FAILURE; if (inst) { status = AXIS2_SVC_SKELETON_FREE(inst, env); } return status; }
- 启动VS控制台(必须是VS控制台,cmd会报错),使用以下命令编译,生成中间文件hello_svc.obj
cl.exe /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AXIS2_DECLARE_EXPORT" /D "AXIS2_SVR_MULTI_THREADED" /w /nologo /I %AXIS2C_HOME%/include /c hello_svc.c
- 使用以下命令链接,生成hello.lib、hello.exp、hello.dll
link.exe /nologo /LIBPATH:%AXIS2C_HOME%/lib axutil.lib axiom.lib axis2_parser.lib axis2_engine.lib /DLL /OUT:hello.dll *.obj
- 在AXIS2C_HOME\services下新建hello文件夹,将hello.dll复制至该文件夹
- 在hello文件夹下新建services.xml,编写内容如下:
<service name="hello"> <parameter name="ServiceClass" locked="xsd:false">hello</parameter> <description> Quick start guide hello service sample. </description> <operation name="greet"/> </service>
- 运行AXIS2C_HOME\bin\axis2_http_server.exe(如之前已运行则需重新启动),通过浏览器访问 http://localhost:9090/axis2/services即可看到新增的Hello服务:
- 为服务提供WSDL。Axis2/C不支持WSDL动态生成,但是可以通过将用于生成服务框架的合约(contract,这里应该指的是静态WSDL文件)和相应的服务建立连接来实现该功能。可以通过两种方式实现上述目标:
- 将WSDL文件添加到服务DLL所在的文件夹中,WSDL文件名称需与服务名称一致
- 在services.xml中提供WSDL文件路径,例如:
<parameter name="wsdl_path">PATH</parameter>
- 静态WSDL文件可以通过在service结尾增加?wsdl访问,例如对与Calculator服务,可通过浏览器访问http://localhost:9090/axis2/services/Calculator?wsdl