注:新版本NLPIR的JNI接口支持配置,可以将链接库和Data目录定义到配置文件中,但好像不支持UTF-8编码。
由于项目中要应用分词,因此前几天的时候了解了一下中文分词系统NLPIR(又叫ICTCLAS2013)的应用,并写了一篇学习笔记:
http://blog.csdn.net/zhangyihui1986/article/details/9167593
前面只是记录了一下在普通的Java工程中如何使用NLPIR,相对来说很简单,使用起来比较容易;但我们的项目是Web项目,因此从前天开始试着将NLPIR整合到Web工程下。还真是遇到了麻烦,主要也是因为第一次使用JNI,对其不够熟悉,折腾了许久才成功运行分词示例,这里记录一下。
起初以为跟普通项目一样,等我把东西都拷到项目中运行示例程序时,报了一个异常:
Caused by: java.lang.UnsatisfiedLinkError: no NLPIR_JNI in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738) at java.lang.Runtime.loadLibrary0(Runtime.java:823) at java.lang.System.loadLibrary(System.java:1028) at kevin.zhang.NLPIR.<clinit>(NLPIR.java:132)
摆弄了很久都是UnsatisfiedLinkError,突然看到了“no NLPIR_JNI in java.library.path”这句话。不是说在java.library.path 中找不到吗?我把库文件移到 java.library.path 中总没什么可说的了吧!然后我就在Web项目中将 java.library.path 这个系统属性输出了一下,结果出来两个路径:
这么说java.library.path系统属性在Windows系统下由两个路径组成,第一个是JDK安装目录下的bin目录;第二个是Tomcat安装目录下的bin目录(我用的服务器是Tomcat,其它的服务器不确定是什么情况,请自行测试)。
这下就好办了,直接将 NLPIR.dll 和 NLPIR_JNI.dll 拷到这两个路径中的其中一个,运行,成功加载!!!
如果我们跟着代码去JDK源码查看一下,最终会追踪到ClassLoader的loadLibrary方法中,其代码如下(整理过):
static void loadLibrary(Class fromClass, String name, boolean isAbsolute) { // 一些其它代码 ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader(); if (sys_paths == null) { usr_paths = initializePath("java.library.path"); sys_paths = initializePath("sun.boot.library.path"); } if (isAbsolute) { if (loadLibrary0(fromClass, new File(name))) { return; } throw new UnsatisfiedLinkError("Can't load library: " + name); } // 删除一些代码 for (int i = 0 ; i < sys_paths.length ; i++) { File libfile = new File(sys_paths[i], System.mapLibraryName(name)); if (loadLibrary0(fromClass, libfile)) { return; } } if (loader != null) { for (int i = 0 ; i < usr_paths.length ; i++) { File libfile = new File(usr_paths[i], System.mapLibraryName(name)); if (loadLibrary0(fromClass, libfile)) { return; } } } // Oops, it failed throw new UnsatisfiedLinkError("no " + name + " in java.library.path"); }
综上所述,在Windows系统上的Web项目中应用NLPIR分词系统至少有三个地方可以放置我们的dll文件(在本人机器环境上如此,不保证所有Windows系统都是如此,请自行测试):
在我的机器上就是:C:\Java\jdk1.6.0_45\bin 、 C:\Java\jdk1.6.0_45\jre\bin 和 E:\servers\apache-tomcat-6.0.37\bin 三个路径。
另外,JNI接口NLPIR静态块中的加载也可以换成System.load()方式,这里需要传递加载库的绝对路径,暂时没有测试!!!
我的开发环境是Windows,但项目最终会部署到Linux系统上,于是今天下午又在Linux上调试了一下,有了前面的经验,Linux上就轻车熟路了。项目不需改动,需要改动的就是NLPIR的库文件了。
Linux环境所需要的库文件是 libNLPIR.so 和 libNLPIR_JNI.so 两个(由于Linux系统和Linux上的JDK都是64位的,所以我下载的是64位的库),其它所需Data目录和Java接口与Windows一样。
首先在Linux上查看了一下 java.library.path 所包含的路径,结果如下所示:
于是我将两个库文件放到了 /usr/local/lib 目录下,启动Tomcat,访问,结果证明这样做是可以的!!!
按理说,上面图片中列出来的所有路径都应该可以的,但我没有挨个测试。
注:在Web项目中,NLPIR.NLPIR_Init初始化方法中的路径参数用的是绝对路径。