1.7 Hprose 过滤器
有时候,我们可能会希望在远程过程调用中对通讯的一些细节有更多的控制,比如对传输中的数据进行加密、压缩、签名、跟踪、协议转换等等,但是又希望这些工作能够跟服务函数/方法本身可以解耦。这个时候,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(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 JavaScript 中已经提供了一个现成的 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.js
中,如果需要请单独引用src/JSONRPCClientFilter.js
。
Hprose 过滤器的功能很强大,除了上面这些用法之外,你还可以结合 Hprose 中间件来实现更为复杂的功能。不过这里就不再继续举例说明了。