Skip to content

Hprose 过滤器

小马哥 edited this page Aug 11, 2015 · 1 revision

简介

有时候,我们可能会希望在远程过程调用中对通讯的一些细节有更多的控制,比如对传输中的数据进行加密、压缩、签名、跟踪、协议转换等等,但是又希望这些工作能够跟服务函数/方法本身可以解耦。这个时候,Hprose 过滤器就是一个不错的选择。

Hprose 过滤器是一个接口,它有两个方法:

inputFilter(data, context)
outputFilter(data, context)

其中 inputFilter 的作用是对输入数据进行处理,outputFilter 的作用是对输出数据进行处理。

data 参数就是输入输出数据,它是 Uint8Array 类型的。这两个方法的返回值也是 Uint8Array 类型的数据,它表示已经处理过的数据,如果你不打算对数据进行修改,你可以直接将 data 参数作为返回值返回。

context 参数是调用的上下文对象,我们在服务器和客户端的介绍中已经多次提到过它。

执行顺序

不论是客户端,还是服务器,都可以添加多个过滤器。假设我们按照添加的顺序把它们叫做 filter1, filter2, ... filterN。那么它们的执行顺序是这样的。

客户端的执行顺序

+------------------- outputFilter -------------------+
| +-------+      +-------+                 +-------+ |
| |filter1|----->|filter2|-----> ... ----->|filterN| |---------+
| +-------+      +-------+                 +-------+ |         v
+----------------------------------------------------+ +---------------+
                                                       | Hprose Server |
+-------------------- inputFilter -------------------+ +---------------+
| +-------+      +-------+                 +-------+ |         |
| |filter1|<-----|filter2|<----- ... <-----|filterN| |<--------+
| +-------+      +-------+                 +-------+ |
+----------------------------------------------------+

跟踪调试

有时候我们在调试过程中,可能会需要查看输入输出数据。用抓包工具抓取数据当然是一个办法,但是使用过滤器可以更方便更直接的显示出输入输出数据。

client.js

function log(data) {
    console.log(hprose.BytesIO.toString(data));
    return data;
}
var logfilter = {
    inputFilter: log,
    outputFilter: log
};
var client = hprose.Client.create("http://www.hprose.com/example/", ['hello']);
client.addFilter(logfilter);
client.hello("world", function(result) {
    console.log(result);
});

客户端输出

Cs5"hello"a1{s5"world"}z
Rs12"Hello world!"z
Hello world!

运行时间统计

有时候,我们希望能够对调用执行时间做一个统计,对于客户端来说,也就是客户端调用发出前,到客户端收到调用结果的时间统计。对于服务器来说,就是收到客户端调用请求到要发出调用结果的这一段时间的统计。这个功能,通过过滤器也可以实现。

client.js

function stat(data, context) {
    if ('starttime' in context.userdata) {
        var t = Date.now() - context.userdata.starttime;
        console.log('It takes ' + t + ' ms.');
    }
    else {
        context.userdata.starttime = Date.now();
    }
    return data;
}
var statfilter = {
    inputFilter: stat,
    outputFilter: stat
};
var client = hprose.Client.create("http://www.hprose.com/example/", ['hello']);
client.addFilter(statfilter);
client.hello('world', function(result) {
    console.log(result);
});

客户端输出

It takes 34 ms.
Hello world!

协议转换

Hprose 过滤器的功能不止于此,如果你对 Hprose 协议本身有所了解的话,你还可以直接在过滤器中对输入输出数据进行解析转换。

在 Hprose for HTML5 中已经提供了一个现成的 JSONRPC 的过滤器。使用它,你可以将 Hprose 客户端变身为 JSONRPC 客户端。

JSONRPC 客户端

var client = hprose.Client.create("http://www.hprose.com/example/", ['hello']);
client.filter = new hprose.JSONRPCClientFilter();
client.hello("world", function(result) {
    console.log(result);
});

客户端只需要设置 filter 属性(或者用 addFilter 方法)为一个 JSONRPCClientFilter 实例对象,Hprose 客户端就马上变身为 JSONRPC 客户端了。不过需要注意一点,添加了 JSONRPCClientFilter 的客户端,是一个纯 JSONRPC 客户端,这个客户端只能跟 JSONRPC 服务器通讯,不能再跟纯 Hprose 服务器通讯了,但是跟 Hprose + JSONRPC 的双料服务器通讯是没问题的。

Hprose 过滤器的功能很强大,除了上面这些用法之外,你还可以结合 Hprose 中间件来实现更为复杂的功能。不过这里就不再继续举例说明了。