1.第一个问题:Java调用dll文件
JNative方式调用dll
JNative是一种能够使Java语言使调用DLL的一种技术,对JNI进行了封装,可能有些读者会有这样一个问题,JNative对JNI进行了封装,并且是一种跨语言的使用DLL,会不会在效率方面很不如人意,我可以用我使用Jnative的经验告诉你,不会!因为我用Jnative就是用来处理大量的数据调用,是基于实时数据库接口的调用。而实时数据库的数据量是非常大的。
首先下载JNative,
注意:将JNative解压,并将其中的JNativeCpp.dll拷贝到system32文件夹中,libJNativeCpp.so是linux平台使用的。
(网址:http://blog.csdn.net/a491857321/article/details/51504094)
使用过程出现问题:
1.找不到NISEC_SKSC.dll,出现这个问题是因为我仅仅将NISEC_SKSC.dll文件放到system32下,而NISEC_SKSC.dll有其他dll的引用,所以需要将安装过的税控所有文件拷到system32下
2.找不到JNativeCpp.dll,需要将其放到system32下,同时JNative.jar需要放到jdk和jre目录下面
配置classpath添加JNative.jar的路径
2.第二个问题。xml与bean转换
采用XStream读取返回信息转为bean
3.第三个问题。传递xml报文,编码问题,一定要写成gbk编码
public static String getPKServerResult(String xmlcontent, Object... objs) {
logger.info("log输入为======\r" + xmlcontent);
Pointer pIn = null;
Pointer pOut = null;
try {
String res = JNAUtil.class.getClassLoader().getResource("NISEC_SKSC.dll").getFile();
// 加载动态库及函数
JNative jnPKServer = new JNative("NISEC_SKSC.dll", "PostAndRecvEx");
byte[] bytes = (xmlcontent + '\0').getBytes("GBK");
MemoryBlock memoryBlockIn=MemoryBlockFactory.createMemoryBlock(bytes.length);
pIn = new Pointer(memoryBlockIn);
// 设置传入参数
pIn.setMemory(bytes);
jnPKServer.setParameter(0, pIn);
// 处理传出参数
if (objs != null && objs.length == 1 && objs[0] instanceof Number) {
MemoryBlock memoryBlockOut=MemoryBlockFactory.createMemoryBlock(((Number) objs[0]).intValue());
pOut = new Pointer(memoryBlockOut);
} else {
MemoryBlock memoryBlockOut=MemoryBlockFactory.createMemoryBlock(1000000);
pOut = new Pointer(memoryBlockOut);
}
jnPKServer.setParameter(1, pOut);
// 执行调用
jnPKServer.invoke();
// String bak ="";
// String bak =pOut.getAsString();
byte[] mm=pOut.getMemory();
String bak = new String(mm,"GBK");
// String bak = new String(pOut.getAsByte(0),"GBK");
// for(int i=0, sumi=((Number) objs[0]).intValue(); i< sumi; i++){
// bak+=((char) pOut.getAsByte(i));
// }
logger.info("log输出为======\r" + bak);
return bak.trim();
} catch (Exception e) {
logger.error("Jnative遇到错误", e);
} finally {
try {
if (pIn != null) {
pIn.dispose();
}
if (pOut != null) {
pOut.dispose();
}
} catch (NativeException e) {
logger.error("Jnative遇到错误", e);
}
}
return null;
}
网址:http://bbs.csdn.net/topics/390806040,String就是一段字符串,需要通过byte[]进行编码的操作
到此技术点基本搞定了,突然有一天客户打电话说网页打不开了,看了一下,tomcat关掉了,开启后,运行一段时间又挂了。。。后来想想可能是因为JNA需要申请内存空间,如果一次申请太多,会导致程序异常,所以将调用接口改为递归形式,每次只读一个开票设备一天的数据。问题解决了,看一下效果吧