java调用.Net的类库dll文件
最近项目开发中,需要用java去调用.net开发团队提供的service。一开始以为是以url形式提供的webservice去调用。后来才知道.net项目组提供给我们一个dll文件说里面有有两个方法供调用,一个是发送邮件的,一个是发送短信的。那么如何在通过java去调用这个用C#实现的类库中的方法呢。通过搜索一些资料最后终于实现了,下面说说是如何实现的,挺有意思的
一、实现方法的选择
1、基本概念的介绍
DLL:动态链接库(Dynamic Link Library,缩写为DLL)是一个可以被其它应用程序共享的程序模块,其中封装了一些可以被共享的例程和资源。动态链接库文件的扩展名一般是dll,也有可能是drv、sys和fon,它和可执行文件(exe)非常类似,区别在于DLL中虽然包含了可执行代码却不能单独执行,而应由Windows应用程序直接或间接调用。
TLB(TLB=Lib): .lib是在你的程序编译连接的时候就连接的文件,因此你必须告知编译器连接的lib文件在那里。一般来说,与动态连接文件相对比,lib文件也被称为是静态连接库。
COM组件: 标准的 COM 组件存在 方式有两种, 一种是你看到的 DLL 还有一个方式是 EXE (进程外).
注:关于DLL和TLB的区别详细信息请参考如下资源
http://www.goupaiba.com/redirect.php?fid=21&tid=82&goto=nextoldset
http://www.winu.cn/ask/question.php?qid=18229
2、Java调用DLL文件的几种方法
使用Java调用DLL动态链接库的方案通常有三种:JNI, Jawin, Jacob。
其中JNI(Java Native Interface)是Java语言本身提供的调用本地已编译的函数库的方法,本身具有跨平台性,可以在不同的机器上调用不同的本地库。
Jawin和Jacob都是sourceforge.net的开源项目,都是基于JNI技术的依赖Windows的实现,使得在Windows平台下使用COM和DLL的更加方便。
JNI介绍:
sun相关文档:http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.html
JNI的完整例子 :http://www.pconline.com.cn/pcedu/empolder/gj/java/0506/642328.html
JNI的应用方案是基于Java类和本地函数相映射的。其使用DLL的步骤还是相对比较麻烦,不但涉及到Java编程,还涉及到C/C++编程。
JaWin介绍:
官方网站:http://jawinproject.sourceforge.net/
官方文档(Jawin介绍): http://jawinproject.sourceforge.net/jawin.html
官方文档(Jawin使用DLL):http://jawinproject.sourceforge.net/jawinuserguide_dll.html
官方文档(Jawin数据指令): http://jawinproject.sourceforge.net/instruction_docs.html
Jacob介绍:
官方文档:http://danadler.com/jacob/
Jacob是Java-Com Bridge的缩写,也可以用来调用DLL。其底层也是使用JNI实现,也具有Windows 的平台依赖性,由于网上有人反映其易用性不如jawin,所以没有深入了解。
二、 Java调用.Net产生的DLL
实例讲解:
准备工作:
1. 在http://jawinproject.sourceforge.net/上下载JaWin工具包
2. 配置:
将jawin.jar放于%JAVA_HOME%\jre\lib\ext下。
将jawin.dll放于c:\winnt\system32下。否则将出现错误:COMException : no jawin in java.library.path;
3. 安装.netFrameWork环境。
环境已经配置好了,下面我们就从开始动手实现;
1、新建如下两个cs文件
HelloFromNETItf.cs
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace Org.Jawin.NETTest { public interface HelloFromNETItf { void ShowDialog(string str); void test(string s); } }
HelloFromNET.cs
using System; using System.Runtime.InteropServices; // necessary for the Guid and ProgId attributes namespace Org.Jawin.NETTest { public class HelloFromNET : HelloFromNETItf { // Need a public default no-arg constructor for COM Interop. public HelloFromNET() { } public void ShowDialog(string str) { Console.WriteLine(str); } public void test(string s) { Console.WriteLine("test" + s); } } }
说明:上面的两个.cs文件相当于我们java中的两个.java文件。声明了一个接口,接口中声明了两个方法。另一个类去实现这个接口。
2.把上面写好的两个文件编译成.DLL文件
1首先找到.netFrameFork的安装路径类似如下
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
把这个路径配置到系统的环境变量path下,这样我们就可以方便的使用.net提供的一些命令了。比如我们下面要用到了csc命令和regasm命令。
2cmd命令进入命令行提示符界面,路径定位到两个cs文件存放的位置
输入csc /target:library /out:hellotest.dll *.cs把两个文件编译成hellotest.dll
C:\>csc /target:library *.cs /r:c:\LotusMail.dll /r:c:\ Interop.Domino.dll
C:\>csc /target:library *.cs /r:c:\SendMail.dll /r:c:\SendSMTPdll /r:c:\ Interop.Domino.dll
输入regasm /tlb hellotest.dll命令生成hellotest.tlb文件
到现在位置我们要调用的dll文件就做好了。
3.编写cs文件调用dll,并作为中间件共以后Java调用
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace Org.Jawin.NETTest { [Guid("3823a63d-5891-3b4f-A460-DB0FB847075F")] public interface TestHelloFromNETItf { void ShowDialog(string str, string caption); } }
上面的连个文件实现了调用我们生成的DLL
注意:上面的接口和实现类和我们做dll时基本是一样的只是多了
[Guid("25c2f5a2-1afe-36ce-BE27-84E040F5E19F")]
[ProgId("Jawin.HelloFromNET6")] // Register the CLSID under this shortcut
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("ea17fc17-9995-425c-bf18-62c02087bdd6")]
至于guid的生成方法如下:
using System; using Org.Jawin.NETTest; using System.Reflection; using System.Runtime.InteropServices; namespace Org.Jawin.NETTest { [Guid("25c2f5a2-1afe-36ce-BE27-84E040F5E19F")] [ProgId("Jawin.HelloFromNET6")] // Register the CLSID under this shortcut ProgId public class TestHelloFromNET : TestHelloFromNETItf { // Need a public default no-arg constructor for COM Interop. public TestHelloFromNET() { } public void ShowDialog(string str,string caption) { System.Reflection.Assembly ass; Type type; Object obj; ass = Assembly.Load("hellotest"); type = ass.GetType("Org.Jawin.NETTest.HelloFromNET"); MethodInfo[] miarr = type.GetMethods(); obj = ass.CreateInstance("Org.Jawin.NETTest.HelloFromNET"); MethodInfo method = type.GetMethod("ShowDialog"); method.Invoke(obj, new string[] { "WriteString"}); //Org.Jawin.NETTest.HelloFromNETItf hfn = new HelloFromNET(); //hfn.ShowDialog(str); Console.WriteLine("testtttttttttttttttttttttttt"); } } }
上面的连个文件实现了调用我们生成的DLL
注意:上面的接口和实现类和我们做dll时基本是一样的只是多了
[Guid("25c2f5a2-1afe-36ce-BE27-84E040F5E19F")]
[ProgId("Jawin.HelloFromNET6")] // Register the CLSID under this shortcut
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("ea17fc17-9995-425c-bf18-62c02087bdd6")]
至于guid的生成方法如下:
输入guidgen命令会出现如下窗口
选择第四个registry 然后点new guid在copy放到我们的cs文件上即可。
接下来我们用上面同样的命令把这两个文件编译成dll文件和tlb文件。
注意:生成的dll文件和tlb文件要放在下面目录中的
%WINDIR%/system32
, %JAVA_HOME%/bin
or %JAVA_HOME%/jre/bin
其中一个,一般都放在
%JAVA_HOME%/bin
下,如果后面
java
调用
dll
的时候报错可以尝试放在其他目录尝试。
到此位置.net方面的工作我们就做完了。下面我们开始编写java代码调用dll中间件。
/*
* HelloFromNETItf.java -
*
* This file is part of the Jawin Project: http://jawinproject.sourceforge.net/
*
* Please consult the LICENSE file in the project root directory,
* or at the project site before using this software.
*/
/* $Id: HelloFromNETItf.java,v 1.2 2004/07/18 14:56:59 arosii_moa Exp $ */
package demos;
import org.jawin.*;
/**
* Modified version of JTB generated code
*
* @version $Revision: 1.2 $
* @author Morten Andersen, arosii_moa (at) users.sourceforge.net
*/
public class HelloFromNETItf extends DispatchPtr {
public static final GUID DIID = new GUID("{3823a63d-5891-3b4f-A460-DB0FB847075F}");
public static final int iidToken;
static {
iidToken = IdentityManager.registerProxy(DIID, HelloFromNETItf.class);
}
/**
* The required public no arg constructor.
* <br><br>
* <b>Important:</b>Should never be used as this creates an uninitialized
* HelloFromNETItf (it is required by Jawin for some internal working though).
*/
public HelloFromNETItf() {
super();
}
/**
* For creating a new COM-object with the given progid and with
* the HelloFromNETItf interface.
*
* @param progid the progid of the COM-object to create.
*/
public HelloFromNETItf(String progid) throws COMException {
super(progid, DIID);
}
/**
* For getting the HelloFromNETItf interface on an existing COM-object.
* This is an alternative to calling {@link #queryInterface(Class)}
* on comObject.
*
* @param comObject the COM-object to get the HelloFromNETItf interface on.
*/
public HelloFromNETItf(COMPtr comObject) throws COMException {
super(comObject);
}
/**
* For creating a new COM-object with the given clsid and with
* the HelloFromNETItf interface.
*
* @param clsid the GUID of the COM-object to create.
*/
public HelloFromNETItf(GUID clsid) throws COMException {
super(clsid, DIID);
}
public int getIIDToken() {
return iidToken;
}
/**
*
* @param str
* @return void
**/
public void ShowDialog(String str,String caption) throws COMException
{
invokeN("ShowDialog", new Object[] {str,caption});
}
}
/*
* HelloNET.java -
*
* This file is part of the Jawin Project: http://jawinproject.sourceforge.net/
*
* Please consult the LICENSE file in the project root directory,
* or at the project site before using this software.
*/
/* $Id: HelloNET.java,v 1.1 2004/07/05 11:55:59 arosii_moa Exp $ */
package demos;
import org.jawin.GUID;
import org.jawin.win32.Ole32;
/**
* Demo showing how to call .NET code published as a COM object.
* The .NET C# source is in the demos/net folder.
*
* @version $Revision: 1.1 $
* @author Morten Andersen, arosii_moa (at) users.sourceforge.net
*/
public class HelloNET {
/**
* CLSID for the HelloFromNET COM object
*/
public static final GUID CLSID = new GUID("{25c2f5a2-1afe-36ce-BE27-84E040F5E19F}");
/**
* ProgID for the HelloFromNET COM object - could be used instead of the CLSID
*/
public static final String PROG_ID = "Jawin.HelloFromNET6";
public static void main(String[] args) {
try {
Ole32.CoInitialize();
HelloFromNETItf hello = new HelloFromNETItf(PROG_ID);
// hello.setCaption("Jawin .NET test");
hello.ShowDialog("Hello from .NET","test");
hello.close();
Ole32.CoUninitialize();
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的2个java文件实现了调用.net中间件。