一个简单嵌入式WEB业务应用设计

来源:互联网 发布:java 就业班 编辑:程序博客网 时间:2024/06/04 18:46

一个简单嵌入式WEB业务应用设计

         主要是针对之前产品中WEB应用的设计的重构,把业务与一些东西分离出来,方便维护,本身比较简单, 注意这个不是说写WEB服务程序的。

工具

goahead

json-c

jquery

数据交互

WEB服务与主应用交互

WEB服务进程同应用进程在同一个嵌入式系统中,两个进程的交互使用UNIX域UDP方试通讯,主要的是数据是,WEB前端的数据请求,数据的提交或控制命令,数据都用json的格式传输。

         WEB服务与WEB前端交互

         WEB前端的HTML请求都通过goahead处理了,在数据上面,我们用AJAX传输JSON的方式,goahead通过UDP服务转给主应用,主应用处理后返回进goahead,再回应给WEB前端。

         之所以用UNIX域UDP通信,一个是速度,也可靠,JSON交换的数据也不是太大,双向通信,简单,包与包之前不用再去分隔了。

WEB服务端

         Web服务使用开源的goahead这个工具,它相对于WEB前端来说是一个服务端,在与我们的主应用来说又是一个UNIX域UDP客户端。

         WEB服务端的初始化

         Goahead的初始化可以参见它的例子中,其实我对这个工具也不太熟悉,在它提供的例子里来改一下,它的初始化操作中有一个initWebs 的过程,这里面设置了一些必要的参数,如默认的网页,比如我的设置的是 index.html 是一个宏定义的:

 

#define WEBS_DEFAULT_HOME       T("index.html")/* Default home page */

#define WEBS_DEFAULT_PORT       80     /* Default HTTPport */

#defineWEBS_DEFAULT_SSL_PORT   433    /* Default HTTPSport */

 

分别定义了默认的主页,端口。

         因为要与主应用中通讯,使用的是UNIX的域UDP方式,所以在goahead里我们要初始创建一个socket的来与主应用交互。

         在一个合适的地方,定义一个Web_Client_init,它的作用就是初始化创建一个UNIX的域UDP socket而已,所以在initWebs中调用过程: Web_Client_init()。

         在一个合适的地方,定义一个 int Web_Client_Send(char* buf, int len, char* recvbuf, int* maxlen), 用它来把WEB前端的数据转发给主应用,同时接收主应用的回应。

 

         在goahead里接收WEB前端过来的AJAX 请求json数据,做如下的动作:

        

设置一个URL请求的处理过程:

websUrlHandlerDefine(T("/ajax/json_data"),NULL, 0, ajax_json_data, 0);

这果 URL 为 http://xxxx/ajax/json_data 这样的URL过来的数据,都传给ajax_json_data处理了。如我的如下的处理,

 

#define RECV_BUF_LEN 2048

static charRECV_BUF[RECV_BUF_LEN];

int ajax_json_data(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,

        char_t *url, char_t *path, char_t *query)

{

    int ret;

    char* data = websGetVar(wp,T("data"),"");

    int len =strlen(data);

    //ret = WebMsg_Send(data, len);

    //char recvbuf[1024] = {0};

    int recvlen = RECV_BUF_LEN;

    RECV_BUF[0]= 0;

    ret= Web_Client_Send(data, len, RECV_BUF, &recvlen);

    if(ret == 0)

    {

        if(recvlen == 0)

        {

            websWrite(wp,T("{status:'failed', data:'Server nodata!'}"));

        }else{

            websWrite(wp,RECV_BUF);

        }

    }else{

        websWrite(wp,T("{status:'failed'}"));

    }

    websDone(wp,200);

    return 1;

}

        

一般JSON的请求数据都不大太,注意空间的分配,上面的过程就是调用 Web_Client_Send 把数据发给主应用,主应用处理完后,同样返回的是JSON格式的应答,获取主应用的应答后通过websWrite写回给WEB前端,注意 websGetVar 获取数据的方式,找的是名为”data”的,这个是在WEB网页中JS里定义的,原因是我们的JS代码是这样写的:

functionajaxActionWrap(actionData, callback)

{

    $.post(URL_AJAX_ACTION,

        {

            data: actionData,

        },

        function(data, status){

            if(callback)

                callback(data, status)

        }

    );

}

 

这样完成后,我们的WEB服务端的事就完成了,它的作用就是负责传输数据,把它同业务分它了。

 

 

主应用

主应用的一个任务是要接收WEB服务传过来的WEB前端请求。

创建一个UNIX域UDP服务。比如我们在一个合适的地方创建一个初始化启动服务的方法: Web_Server_Init(),这样就能接收到WEB的请求了。

另一个任务就是对WEB的AJAX JSON请求的处理回应了。

不同的JSON调用,针对不同的业务,所以我们定义一个记录不同业务处理过程的结构:

比如:

typedef int (*JsonActionProc)(char* data, void* jsonobj,AjaxActionProcCallBack cb);

 

typedef struct _WebAjaxAction{

        char*actionName;

        JsonActionProc actionProc;

}WebAjaxAction;

 

actionName是对应处理方法的标识,如WEB前端传一个这样的JSON数据过来:

{"action":"wifi_status","data":{"p1":1,"p2":2}}

那么 wifi_status 就是对应actionName.

 

记录注册每一个json里的action调用过程,如:

static WebAjaxActionwebAjaxActionList[] = {

        {"wifi_status",wifi_status},

        {"wifi_scan",wifi_scan},

        {"wifi_get_aplist",wif_get_aplist},

        {"wifi_conn",wifi_conn},

        {"wifi_getAplist",wifi_getAplist},

};

像wifi_status,wifi_scan… 这些都是调用方法的标识,这个要与WEB前端协商好,保持一致。

actionProc 参数就是对应的调用方法了。

上面的过程,也就是如 WEB 传一个JSON数据过来,它里面有对应的actionName,通过actionName找到对应的业务方法,JSON里也会有一些参数,把JSON里的数据解析出来,调用对应的业务方法就行了,同时把处理的过后的数据通过WEB服务端返回的WEB前端。

 

从上面的过程,来说,调用recvfrom接收到数据报后,调用一个过程,从webAjaxActionList 里找到对应的处理方法,调用处理方法,处理方法完成后,把要返回的数据通过sendto 再回到WEB服务端,再返回的WEB前端。整个过程就完事了。

WEB前端

完成上面的东西,WEB前端就可认方便的调用了,当HTML显示加载完成后,再通过AJAX的方式,用JSON的格式来调用数据。

如我的获取一个WIFI的连接状态,当然,交互的JSON数据需要WEB前端与主应用后端要协商好,用什么样的格式,比如我的是:

{"action":"wifi_status"}

表示调用的方法是 wifi_status

 

如下面的几个相关的方法:

 

/*获取WIFI连接状态*/

functiongetWifiStatus()

{

 

         var data ='{"action":"wifi_status"}';

         ajaxActionWrap(data,getWifiStatusCallBack);

}

 

functionajaxActionWrap(actionData, callback)

{

         $.post(URL_AJAX_ACTION,

                   {

                            data: actionData,

                   },

                   function(data, status){

                            if(callback)

                                     callback(data,status)

                   }

         );

}

 

functiongetWifiStatusCallBack(data, status)

{

         if(status != "success")

         {

                   alert("get wifi statusfailed!\n");

                   return;

         }else{

                   var jobj = eval(data)

                   if(jobj)

                   {

                            $("#wifiCurAp").html(jobj[0].wifi_status.ssid);

                            if(jobj[0].wifi_status.status== 1)

                                     $("#wifiCurStatus").html("已连接");

                            else

                                     $("#wifiCurStatus").html("未连接");

                   }else{

                            $("#wifiCurStatus").html("未连接");

                   }

         }

}

 

在后端,它会找到wifi_status的对应处理方法,处理后返回定义好的JSON数据格式,WEB前端再显示出来。

 

最后

通过上面的处理方式,对于主应用来说,把业务相关的都隔离开了,在对应的处理方法中,WEB服务端只负责传输数据,WEB前端通过AJAX的方式传输JSON数据和接收,通过JS脚本控制。

在添加新的业务时,也只要修改WEB前端的JS脚本,主后端注册一下处理的方法就行。

注:对WEB应用只懂一点点,对上面的实现提一点注意的地方:

1:JS脚本里最好不要用eval转换数据生成对像,不安全,可以用jQuery里的对应工具。

2:AJAX的请求认证,一定要记得添加,像上面的应用的话,比较好的方式可以加在WEB服务端的ajax_json_data 里,在请求后端应用时,验证一下,见很多产品,AJAX请求尽然没有验证权限。

0 0
原创粉丝点击