5.5 客户端开发


  • 5.5.1 Javascript客户端

    前面的几个实验已经涉及到了javascript开发,这里只需要明确客户端名字空间组织方式即可。

    对照template.js可以看出,客户端所有数据全部挂接在以ctx为根的一棵树上。在上面的实验中适当位置console.log(ctx);即可输出这棵树,一层一层讨论。

    • 第一层

      100, 即为当前请求服务的PVID,如果有一个客户端请求多个,则会并列出现多个。

      f: -1, auany返回的状态标记,和认证模块相关。

      i: 57344, 用户的SessionId

      onclose,onerror,onopen, template.js中设定的网络消息handle。

      register, 这个方法是系统注入的,如果view的字段太多,需要单独监听个别字段的变化,可以使用register。三个参数,r为view对象;v为需要监听的字段名;f为监听器,参数解释与onchange一样。

      send, 这个方法是系统注入的,用于向服务器发送控制消息。两个参数,r为view对象,s为需要发送的消息字符串。


    • 第二层

      这里可以看见按服务器xml描述中的名字空间组织起来的三种View。

      观察example.share.xml:

      example.share.html


      <namespace name="share" pvid="100">
      

      这里可以看到share和pvid=100是并列的,为什么会专门制造一个层次出来?

      原因在于客户端框架允许连接同一运营体系下多个服务,换言之,即是连接多组xml定义的项目,所以无法保证两个项目没有使用一样的最外层名字空间名,只有pvid能做出正确的区分。.


    • 第三层

      这一层需要分两组讨论,GlobalView,SessionView一组,TemporaryView一组。

      全局View和会话View:

      对待SessionView的观点,与服务器不同,一个客户端的Session自然只能有1个,所以从客户角度来看与GlobalView应该同等对待,这里用MySessionView解释:

      __c__: 1, 这个是生成服务器代码时提供给各个View的唯一编号。

      __n__: "share.MySessionView"很明确,View的名字。

      __p__: pvid, 既然View上没有类似__parent__的字段引用回上层,记录在这里就行了。

      onchange: template.js注入的这个View的监听器。

      var0: 这就是这个View定义的字段。

      这里需要注意, xml描述里面定义了的字段这里可能没有,要么是没有初始化,要么就是删除了。


      临时View:

      1: Object, 这个1是临时View的instanceid,一个临时View允许有多个实例,在这里进行区分。

      __c__, __n__, __p__, 同上。

      onchange: template.js 注入的这个View的监听器模板

      onopen: 服务器通告临时View创建时调用,参数一为临时View的instanceid,参数二为当前临时View的成员sessionid数组,这里将onchange方法的引用拷贝给了创建出来的临时View实例。

      onattach: 新成员加入临时View时调用,参数一为临时View的instanceid,参数二为新成员的sessionid。

      ondetach: 成员离开临时View时调用,参数一为View的instanceid,参数二为离开成员的sessionid,参数三为离开原因。

      onclose: 服务器关闭临时View时调用,参数为临时View的instanceid。


    • 第四层

      展开临时View实例,进入第四层

      57344: Object, 这是sessionid=57344的用户的被订阅信息,如果临时View有多个用户加入,会并列多个。上文实验7的图2,能清楚看到这一点。

      __i__: 1, 代表了instanceid = 1

      __c__, __n__, __p__, 同上。

      onchange: 之前onopen的时候拷贝过来的那个onchange。

      临时View定义的variable,bind字段也应该在这一层,这里可以看出服务器没有创建出来。


    • 第五层

      展开临时View的sessionid=57344用户的订阅信息

      这里看到订阅字段_var0对于sessionid=57344的用户而言是"onAttached 57344"


    • 几点说明

      1. 分析template.js代码可得出结论,全局View和会话View,在ctx.open被执行之前就已经创建出来,等待服务器的数据改变通告;临时View, 在ctx.open被执行之前仅仅创建了一个模板, 只有等到模板上的onopen被调用前才真正创建出临时View实例, 按instanceid区分挂接在模板上。

      2. onchange消息e中e.sessionid比较特殊, 除了通告临时View订阅字段变化时, 使用发生变化的那个成员的sessionid, 使用当前用户的sessionid。仔细观察上文实验7的图二的第二,可以看到这一情况。

      3. 全局View,会话View的字段可以标识为:


      ctx[pvid].path_to_view.fieldname
      

      临时View的variable,bind字段可以标识为:


      ctx[pvid].path_to_view[instanceid].fieldname
      

      临时View的subscribe字段可以标识为:


      ctx[pvid].path_to_view[instanceid][sessionid].fieldname
      

      T在这里,path_to_view解释为xml描述中service节点下的manager节点通过state节点引用的名字空间到View的路径名。

      4. 使用javascript脚本客户端,定义View的字段时避免使用onXXX,__XXX__命名,防止命名冲突。


  • 5.5.2 最简单服务器

    为了实验后面各种客户端实现,这里首先提供一个足以说明问题的最简单服务器,以及chrome演示结果用以对比。

    清理掉前面实验中的所有修改,然后:

    MySessionView.java


    private MySessionView(SessionView.CreateParameter param) {
        super(param);
        // bind here
        long sessionid = param.getSessionId();
        setVar0("Hello " + sessionid);
        MyTemporaryView.createInstance().getMembership().add(sessionid);
    }
    
    protected void onControl(_MySessionView.control param, long sessionid) {
        onMessage(Integer.toString(param.var0), sessionid);
    }
    
    protected void onMessage(String message, long sessionid) {
        setVar0(message);
    }
    

    example.html


    v100.share.MyTemporaryView.onopen = function(instanceid, memberids) {
        this[instanceid].onchange = this.onchange;
        console.log("v100.share.MyTemporaryView.onopen", this[instanceid], instanceid, memberids);
        ctx.send(v100.share.MySessionView, "99999");
    }
    

    注意加入的最后一句send,临时View onopen的时候发送一个控制触发一次改变动作。


上一页 下一页