7.8 Node.js兼容框架

Limax集成原生java版本node.js兼容框架,使用JDK8提供的Nashorn引擎,依据node.js手册的描述实现,并做了适当扩展,以利于集成到Limax框架中,为连接Limax外的系统提供便利。

Nashorn支持ES5.1标准,对于某些ES6标准的js文件,应该首先使用6to5工具转换,现有Node.js手册示例都是ES6代码,应该转换以后实验。

以下的描述,符合node.js 6文档的顺序,便于对比。


  • 7.8.1 核心模块

    除了Buffer模块比较特殊, 放在包limax.node.js内, 其它核心模块均放置在包limax.node.js.modules内, 一个.java文件一个.js文件配对, 按照java习惯, 首字母大写, require时全小写。

    • Assert(断言)

      功能与标准node.js一致。AssertionError类做了一些信息伪造。实际上,js中,Error类无法被有效继承,特别是在stack的问题上。


    • Buffer

      不同于其它核心模块的对象, Buffer不是js对象, 直接导出了limax.node.js.Buffer对象。原因在于, node.js文档描述了[]操作, 但是ES5.1标准不支持索引化属性的访问, 所以使用了Nashorn的一个怪异特性, 实现了List接口的对象可以用[]方式问, 带来的问题是BoundCheck在Nashorn中完成, 数组越界会直接抛出异常, 这一行为与js不一致。 最好避免使用[]访问Buffer。


    • Java插件

      不同于node.js用C++实现,使用C++创建插件。Limax的Node插件用Java创建,一个插件就是一个jar,一个插件jar内部只能有一个js文件,同时保证存在一个相应名字的java类,更多的细节可以参见limax.node.js.modules包。

      例如:

      MyTest.java


      package testnodejsmodule;
      
      import limax.node.js.EventLoop;
      import limax.node.js.Module;
      
      public final class MyTest implements Module {
          public MyTest(EventLoop eventLoop) {
          }
      
          public Number add(Number x, Number y) {
              return x.doubleValue() + y.doubleValue();
          }
      }
      

      MyTest.js


      exports.add = function(x, y) {
          return java.add(x, y);
      }
      

      这样两个程序用eclipse export成一个jar,就可以作为插件被引用。

      将插件命名为 test.jar 放置在主模块目录下,执行主模块


      console.log(require('./test.jar').add(1,2))
      

      即可输出结果3。


      具体细节详见模块一节。


    • Child Processes(子进程)

      使用java.lang.ProcessBuilder操控子进程,支持进程管道操作。

      • 1. 不支持child_process.fork方法,Limax使用线程模型,不需要这个方法,详见模块一节。

      • 2. 类ChildProcess仅支持exit事件(其它事件都与IPC相关, 不需要), 在进程结束后触发。支持child.kill方法, java.lang.Process向进程发送的信号仅支持SIGTERM与SIGKILL, 非SIGKILL的情形, 一律默认SIGTERM。支持child.stdin, child.stdout, child.stderr, child.stdio。

      • 3. 所有方法的options参数中, 支持options.cwd, options.env(Node.js手册中声明spawn方法默认process.env, exec方法默认null, 实际测试exec默认值也是process.env, 所以默认process.env), options.shell, options.detached, options.input, options.timeout, options.encoding, options.maxBuffer, options.killSignal(SIGTERM|SIGKILL), options.stdio(只支持3个标准IO对象)。

      • 4. child_process.spawnSync方法返回的对象,没有pid成员,因为java.lang.Process不提供。


    • Cluster(集群)

      Node.js使用进程模型, 一个进程对应一个Javascript虚拟机, 为了使用cpu的多核特性, 所以提出了集群概念, fork出更多的虚拟机, 使用IPC进行协调。Limax中, 通过扩充require, 允许require传递参数, 允许require创建新的虚拟机实例,完全可以达成同样的目的,而且更节约资源。

      具体细节详见模块一节。


    • CLI(命令行)

      可以在shell中执行,这种情况下 java –jar limax.jar node <module> [args]

      可以作为Limax服务加载,在服务xml配置中添加:


      <NodeService module=module_path>
          <parameter value="0" />
          按参数数量,顺序排列
      </NodeService>
      

      一条NodeService element启动一个javascript虚拟机线程执行module。


    • Console(控制台)

      • 1. console.dir 作为console.log的别名,不支持显示颜色之类的选项。

      • 2. 内部使用java.lang.String.format方法格式化输出字符串, 格式参数与node.js使用的sprintf格式参数稍有差异, 应该注意。如果格式化失败, 按照普通字符串对待。

      • 3. console.timeEnd,用WeakHashMap管理,不删除定时器也不会有泄漏。


    • Crypto(加密)

      • 1. node.js使用openssl实现, limax中主要使用jce实现, 支持的算法集合稍有差异。getCiphers(), getCurves(), getHashes(), 三个方法可以用来获取具体支持的算法, 进行比较。

      • 2. Cipher类没有提供AEAD的支持,因为AEAD的使用流程尚未确定。

      • 3. limax.util.OpenSSLCompat提供了需要的openssl兼容性支持。jce只支持自己的keystore与PKCS11, PKCS12, 这里通过使用limax.codec.asn1包, 提供PEM格式的支持, 这两处代码, 其它地方可能有用。


    • Debugger(调试器)

      Nashorn根本不会生成js字节码,而是直接生成java字节码,深度调试应该使用java的调试器。


    • DNS(域名服务器)

      node.js使用libresolve实现,limax使用jndi实现,所以不提供libresolve规格的错误码。

      特别注意,lookup方法的返回结果,node.js文档描述与实现不一致,文档描述是错误的。


    • Domain(域)

      node.js文档申明该模块是废弃的,所以不提供。


    • Error(错误)

      错误类由Narshorn提供,不需要提供。

      需要注意的是, Limax环境下, 所有通过callback报告的错误, 可能是js的Error, 也可能是java的Exception, 并没有统一成Error, 因为Exception可以提供更丰富的栈信息, 例如:


      function(err) {
          if (err) {
              if (err instanceof Error) {
                  console.log(err.message, err.stack);
              } else {
                  err.printStackTrace();
              }
              return;
          }
      }
      

      这样的处理,可以输出最完整的错误信息。


上一页 下一页