Node.js调用java之node-java问题
作者:我啥都会
故事的起源是这样:
项目中用ioredis封装的模块,在定时、大数据量写入redis的情况下,内存激增,如果不是我对ioredis使用姿势有问题的话,那么就是在这种苛刻的情况下,node招架不住了,然后自然想到了jedis,官方推荐的redis的java客户端,大厂、线上都在大量使用,生态也非常的好。
对于我们要在node中调用java,则基本需求是
(1)、java封装接口,到处jar,node调用jar中的接口,传参拿值;
(2)另一种比较少用,因为通用性不强,node中chilld_process运行jar包,当然jar中需要有java主函数,然后就在另一个线程中运行起来了,就没node什么事情了。
本文主要讲的是第一种需求,因为这才是通用的使用方法。
1、环境搭建
nodejs基本环境是自然的了。
(1)安装java(jdk、jre),自行百度,并配置环境变量;
(2)安装python2版本;
(3)全局安装node-gyp;
npm/cnpm i -g node-gyp
(4)全局安装window-build-tools;(由于下载下来的模块需要编译,所以需要这个工具,如果你本身安装了vs,就不需要这个东西,能自动检测到)
npm i --g --production windows-build-tools
(5)安装node-java模块;
虽然叫node-java,但模块本身是java
cnpm i java
如果(1)~(3)你都配置好了,然后在vscode中运行npm i java时还是出错的话,良好的建议,打开控制台运行,vscode可能存在一些权限问题,至少我遇见过这样的事情,然后按照这种方法就成功了。
2、导出jar包
我使用的时idea,其实各种ide都一个样,都能搞,这里说一下基本步骤:
(1)创建一个java project
(2) 导入相关jar包(Jedis为例)
新建一个jar文件夹,将jars放进去,然后导入项目;
导入jar,点击项目结构进入
然后选择刚刚放置好的jars,点击勾选,确认即可
然后可以开发接口了,这里简单一个写入redis的接口
package com.company; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.Pipeline; public class JedisTool { private Pipeline pl = null; private JedisPoolConfig poolConfig = null; private Jedis jr = null; private JedisPool jedisPool = null; public void initJedis() { this.poolConfig = new JedisPoolConfig(); // 最大连接数 this.poolConfig.setMaxTotal(4); // 最大空闲数 this.poolConfig.setMaxIdle(1); // 最大允许等待时间 this.poolConfig.setMaxWaitMillis(2000); //获得连接池 this.jedisPool = new JedisPool(poolConfig,"127.0.0.1",6379); this.jr = this.jedisPool.getResource(); this.pl = this.jr.pipelined(); } public void usePipeline(int count) { try{ for(int i=0;i<count;i++) { this.pl.set("abcdefgh" + Integer.toString(i), "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" + Integer.toString(i)); } this.pl.sync(); }catch (Exception e){ e.printStackTrace(); }finally { } } public Jedis getClient(){ return this.jedisPool.getResource(); } }
接下来点击项目结构--》Artifact,点击左上加号--》form modules with dependencies
填写主类,这里改成接口类也是可以的(手动改,无法选择接口类)、点击完成、然后点击build--》build artifacts--》build
然后再项目中的out文件夹就生成了jar包。
3、nodejs调用jar
直接看代码吧,这里只是很简单的,但很实用。
let java = require("java"); //引入nodejs的java模块 java.classpath.push("./testJedis.jar"); //导入编写的jar包 let JedisTool = java.import('com.company.JedisTool'); //package.class let jedisTool = new JedisTool(); jedisTool.initJedis(); //方法调用 setInterval(() => { jedisTool.usePipeline(100000); }, 1000);
还有很多使用方法,这里不一一列出了,有了node的java模块,你也可以在node中进行java开发了。
node-java文档 ,官方文档很详细,我虽然英语好,但是也是实在读不下去,挑自己感兴趣的学习即可。
4、心得
本文简单记录了node调用java的方法,在生产项目中会增加许多可能,因为优秀的接口我们都值得使用,不管他是java还是c++。
这个过程中有几点注意事项:
(1)java模块的依赖问题,换台电脑还能不能用之类的事情,最起码要运行的机器需要java环境;
(2)高版本编译的jar,装有低版本java的node调用jar会报错;
(3)openJDK能否正常调用等待明天验证;
(4)jar不能在nodejs的多线程使用,这个问题有待研究。
5、后续验证
(1)java模块的依赖问题,换台电脑还能不能用之类的事情,最起码要运行的机器需要java环境;
这一点在其他机器上(windows)只需要安装同版本的java环境,并且将jvm.dll的路径添加到环境变量path中即可。
(2)openJDK能否正常调用(可以);
由于nodejs安装java模块的时候需要编译且生唉成了一个.node,而.node并不跨平台,所以需要重新编译,在linux下使用java模块同样需要编译(java、javac、node-gyp,g++...)。
但是linux有些系统只安装了java,并没有安装javac,所以需要安装javac,重新编译java模块源码。
然后就可以愉快的使用了。
(3)开启多线程,只能有一个线程运行我们封装的jar包;
经过验证,确实如此,查看官网,说是只能创建一个jvm,线程同属于一个进程,所以之。
突然又会想到,那多进程呢,理论上是可以的,验证之后确实如此,进程之间相互隔离,所以可以创建多个jvm。
6、补充
中标麒麟下运行node调用java的注意事项
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。