项目要求如下:
登录注册页面,注册时需要调用对应提供的delphi写的dll动态链接库,该动态链接库用来加密数据库的。即用户注册后密码需要经该动态链接库加密后存入数据库,使得有系统管理员权限的人员也无法查看真正的用户密码,用户在登录时比较登录时的密码加密后与数据库中存储的密码是否相同,相同则登录成功。
之前没有尝试过在java程序中调用别的语言的DLL文件。首先先展示一下,我在网上下载的示例:
作为纯小白,也先介绍一下我是如何折腾成功的。
1,介绍一下JNA:来自百度百科。
JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。
优点
JNA可以让你像调用一般java方法一样直接调用本地方法。就和直接执行本地方法差不多,而且调用本地方法还不用额外的其他处理或者配置什么的,也不需要多余的引用或者编码,使用很方便。
JNA描述
JNA类库使用一个很小的本地类库sub 动态的调用本地代码。程序员只需要使用一个特定的java接口描述一下将要调用的本地代码的方法的结构和一些基本属性。这样就省了为了适配多个平台而大量的配置和编译代码。因为调用的都是JNA提供的公用jar 包中的接口。
2,已经给出一个delphi写好的DLL文件,在delphi中该文件这样调用(我不懂delphi语言):
function Enc(Str : PChar) : PChar; stdcall; external 'BaseFun.dll'; stdcall;
function Dec(Str : PChar) : PChar; stdcall; external 'BaseFun.dll'; stdcall;
sPass_Word := Enc(PChar(sPass_Word)) ;
sPass_Word := Dec(PChar(sPass_Word)) ;
3,java中需要导入一JNI.jar包,导入到项目中,下面我们要在java中调用该DLL文件。思路如下:1,要加载DLL文件,2,调用该DLL文件中的函数,可以看出该文件中存在Enc函数和Dec函数。3,将数据加密肯定的方式是传入一个参数,返回一个加密后的参数,该参数就是将要存储在数据库中的密码。
关键代码如下:
public interface Enc extends Library{
public String Enc(String str);//定义该接口
}
public static String EncMethods(String str){ //在java中定义该方法,传入一参数,返回加密后的密码
Enc enc=(Enc)Native.loadLibrary("BaseFun",Enc.class);//加载该DLL文件,BaseFun代表文件名,Enc代表该函数
String result=enc.Enc(str);
return result;
}
4,
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'Encc': ?????????
at com.sun.jna.Function.<init>(Function.java:179)
该错误说明在该DLL动态链接库中不存在在Encc函数。
,5,在main方法里面写一测试用例,测试成功,但是在启动tomcat中测试时则出现如下错误,
java.lang.UnsatisfiedLinkError: Unable to load library BaseFun
说明没有成功加载该动态链接库,经查,需要将该DLL文件该为绝对路径,相对路径在这里不可以,博主使用的是windows xp系统。
6,完整代码稍后奉上。
7,关于JNI调用C,C++,delphi写的动态链接库一文章再次奉上,下面内容是我转的,亲测可行,贡献给如我一样小白的网友:
Java调用dll应用在一些java力不能及的地点,不如象和硬件打交道,在就是以前的VC++的DLL的方法可以重用,通过JNI java程序员可以方便地和C++程序员协作
首先书写java类
例如
class ShowMessage
{
static{
System.loadLibrary("showMessage"); //加载的DLL文件名称
}
publicnative static void display(); //本地调用方法接口 必须
publicstatic void main(String args[]) //函数入口 必须
{
ShowMessage.display();
}
}
编译这个类,得到文件ShowMessage.class文件,再调用javah ShowMessage得到ShowMessage.h
文件内容的如下
#include <jni.h>
/* Header for class ShowMessage */
#ifndef _Included_ShowMessage
#define _Included_ShowMessage
#ifdef __cplusplus
extern "C" {
#endif
/*
*Class: ShowMessage
*Method: display
*Signature: ()V
*/这里就是java能调用的方法
JNIEXPORT void JNICALLJava_ShowMessage_display
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
新建一个VC++ dll的工程与上头loadLibrary("showMessage")的名称对应,注意增加编译的include 中加入JDK文件夹下的bin 和win32,
在STD_AFX.cpp中加入
#include “jni.h”
下来就是编辑ShowMessage.cpp文件,实现ShowMessage.h中申明的本地方法
JNIEXPORT void JNICALLJava_ShowMessage_display
(JNIEnv *, jclass){
实现我们需要完成C++代码
这里我只是做一个简单的MessageBox();
MessageBox(NULL,"这是一个java调用DLL的实例","提示框",MB_OK);
}
编译完成之后就能得到ShowMessage.dll
将这个DLL复制到ShowMessage.class 的同名目录下面
调用java ShowMessage就可以得到C++下的MessageBox同样的效果。
实现了java调用C++语言写的DLL文件了。