简介

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

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

  1. inputFilter(data, context)
  2. outputFilter(data, context)

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

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

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

执行顺序

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

客户端的执行顺序

  1. +------------------- outputFilter -------------------+
  2. | +-------+ +-------+ +-------+ |
  3. | |filter1|----->|filter2|-----> ... ----->|filterN| |---------+
  4. | +-------+ +-------+ +-------+ | v
  5. +----------------------------------------------------+ +---------------+
  6. | Hprose Server |
  7. +-------------------- inputFilter -------------------+ +---------------+
  8. | +-------+ +-------+ +-------+ | |
  9. | |filter1|<-----|filter2|<----- ... <-----|filterN| |<--------+
  10. | +-------+ +-------+ +-------+ |
  11. +----------------------------------------------------+

跟踪调试

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

client.js

  1. function log(data) {
  2. console.log(data);
  3. return data;
  4. }
  5. var logfilter = {
  6. inputFilter: log,
  7. outputFilter: log
  8. };
  9. var client = hprose.Client.create("http://www.hprose.com/example/", ['hello']);
  10. client.addFilter(logfilter);
  11. client.hello("world", function(result) {
  12. console.log(result);
  13. });

客户端输出


  1. Cs5"hello"a1{s5"world"}z
  2. Rs12"Hello world!"z
  3. Hello world!

运行时间统计

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

client.js

  1. function stat(data, context) {
  2. if ('starttime' in context.userdata) {
  3. var t = Date.now() - context.userdata.starttime;
  4. console.log('It takes ' + t + ' ms.');
  5. }
  6. else {
  7. context.userdata.starttime = Date.now();
  8. }
  9. return data;
  10. }
  11. var statfilter = {
  12. inputFilter: stat,
  13. outputFilter: stat
  14. };
  15. var client = hprose.Client.create("http://www.hprose.com/example/", ['hello']);
  16. client.addFilter(statfilter);
  17. client.hello('world', function(result) {
  18. console.log(result);
  19. });

客户端输出


  1. It takes 34 ms.
  2. Hello world!

协议转换

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

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

JSONRPC 客户端

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

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

- - -:warning: 注意:该文件并没有打包到 hprose.js 中,如果需要请单独引用 src/JSONRPCClientFilter.js。- - -

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

原文:

https://github.com/hprose/hprose-js/wiki/Hprose-%E8%BF%87%E6%BB%A4%E5%99%A8