基于Axis2/C的Hello World!基础入门

129 阅读3分钟

Axis2/C是一个用C语言实现的Web Service引擎。

Axis2/C基于Axis2架构,支持SOAP1.1SOAP1.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,并加入如下代码:

#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_svc_skeleton_t *)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;
}

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,并插入如下内容:

<?xml version="1.0" encoding="utf-8"?>
<service name="hello">
  <parameter name="ServiceClass" locked="xsd:false">hello</parameter>
  <description>
    Quick start guide hello service sample.
  </description>
  <operation name="greet">
    <parameter name="wsamapping">http://ws.apache.org/axis2/c/samples/hello</parameter>
  </operation>
</service>

9、启动Axis2服务器,执行如下命令:

axis2_http_server

三、访问服务
10、在VS中创建项目Axis2Test,并在  Axis2Test.cpp中插入这些代码:

#include <stdio.h>
#include <axiom.h>
#include <axis2_util.h>
#include <axiom_soap.h>
#include <axis2_client.h>

axiom_node_t *build_om_request(const axutil_env_t *env);
const axis2_char_t *process_om_response(const axutil_env_t *env, axiom_node_t *node);

int _tmain(int argc, char **argv)
{
    const axutil_env_t *env = NULL;
    const axis2_char_t *address = NULL;
    axis2_endpoint_ref_t *endpoint_ref = NULL;
    axis2_options_t *options = NULL;
    const axis2_char_t *client_home = NULL;
    axis2_svc_client_t *svc_client = NULL;
    axiom_node_t *payload = NULL;
    axiom_node_t *ret_node = NULL;

    env = axutil_env_create_all("hello_client.log", AXIS2_LOG_LEVEL_TRACE);
    options = axis2_options_create(env);
    address = "http://localhost:9090/axis2/services/hello";

    if (argc > 1)
        address = argv[1];

    if (axutil_strcmp(address, "-h") == 0)
    {
        printf("Usage : %s [endpoint_url]\n", argv[0]);
        printf("use -h for help\n");
        return 0;
    }

    printf("Using endpoint : %s\n", address);
    endpoint_ref = axis2_endpoint_ref_create(env, address);
    axis2_options_set_to(options, env, endpoint_ref);
    axis2_options_set_action(options, env, "http://ws.apache.org/axis2/c/samples/hello");

    client_home = "E:\\mengli\\axis2c-bin-1.6.0-win32"; // AXIS2_GETENV("AXIS2C_HOME");
    if (!client_home && !strcmp(client_home, ""))
        client_home = "../..";

    svc_client = axis2_svc_client_create(env, client_home);
    if (!svc_client)
    {
        printf("Error creating service client\n");
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:"
                                                " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        return -1;
    }

    axis2_svc_client_set_options(svc_client, env, options);
    payload = build_om_request(env);
    ret_node = axis2_svc_client_send_receive(svc_client, env, payload);

    if (ret_node)
    {
        const axis2_char_t *greeting = process_om_response(env, ret_node);
        if (greeting)
            printf("\nReceived greeting: \"%s\" from service\n", greeting);

        axiom_node_free_tree(ret_node, env);
        ret_node = NULL;
    }
    else
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:"
                                                " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        printf("hello client invoke FAILED!\n");
    }

    if (svc_client)
    {
        axis2_svc_client_free(svc_client, env);
        svc_client = NULL;
    }

    if (env)
    {
        axutil_env_free((axutil_env_t *)env);
        env = NULL;
    }

    return 0;
}

axiom_node_t *
build_om_request(const axutil_env_t *env)
{
    axiom_node_t *greet_om_node = NULL;
    axiom_element_t *greet_om_ele = NULL;

    greet_om_ele = axiom_element_create(env, NULL, "greet", NULL, &greet_om_node);
    axiom_element_set_text(greet_om_ele, env, "Hello Server!", greet_om_node);

    return greet_om_node;
}

const axis2_char_t *
process_om_response(const axutil_env_t *env,
                    axiom_node_t *node)
{
    axiom_node_t *service_greeting_node = NULL;
    axiom_node_t *return_node = NULL;

    if (node)
    {
        service_greeting_node = axiom_node_get_first_child(node, env);

        if (service_greeting_node &&
            axiom_node_get_node_type(service_greeting_node, env) == AXIOM_TEXT)
        {
            axiom_text_t *greeting = (axiom_text_t *)axiom_node_get_data_element(service_greeting_node, env);
            if (greeting && axiom_text_get_value(greeting, env))
            {
                return axiom_text_get_value(greeting, env);
            }
        }
    }

    return NULL;
}

11、编译并执行该程序,会向远程服务发送字符串Hello Service!,并得到响应Hello Client!

出处:原文链接