Java 调用.net dll

环境与工具:

1、.net framework 3.5  C#

2、java jdk1.5,   Tomcat 5.5

3、jacob-1.15-M3

 

实现例子:

一、C# 制作Com组件

新建一个Class 项目,取名TestCom

 

代码

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace TestCom
{
[Guid("E9BCF867-CD81-40d0-9591-ED28D1ED2B53")]
public interface IEncrypt
{
[DispId(1)]
string GetEncrypt(string str,string str2);
}
[Guid("33A6E58D-E1F5-4b53-B2E2-03B9F8BA2FAD"), ClassInterface(ClassInterfaceType.None)]
public class Encrypt:IEncrypt
{
public Encrypt(){}

public string GetEncrypt(string str,string str2)
{

return  ”测试 | ”+str+”|”+str2;
}
}
}

复制代码

 

打开 Project–>  Properties菜单  在Application标签中打开 Assembly Information 将Make assembly Com-Visible一项选中。再切换到Build标签将 Register for COM interop一项选中。

 

Guid的生成:打开Visual Studio Command Prompt 输入guidgen 命令调出工具。类型选择Registry Format,点击New Guid,然后COPY出来。

[DispId(1)]为函数的标识。如果有多个函数可相应的在函数前面加[DispId(2)], [DispId(3)]…

 

设置强名称:打开Visual Studio Command Prompt 输入:sn -k TestComkey.snk 生成TestComkey.snk 文件

打开 Project–>  Properties菜单  在Signing标签中选中 Sign the assembly,选择刚刚生成的强名称文件TestComkey.snk

 

编译程序Debug目录中会生成 TestCom.dll 和TestCom.tlb

手工注册Com方法:

打开Visual Studio Command Prompt进入Debug目录,运行命令注册:

regasm TestCom.DLL /tlb:TestCom.tlb

gacutil -i TestCom.DLL (执行这个命令需要TestCom.DLL 具有强名称)

二、java 调用 Com

部署jacob
1、在开发环境中引入jacob.jar
2、拷贝jacob-1.15-M3-x86.dll 文件到 C:\Windows\System32目录,如果是Web应用的话还需要拷贝到jdk1.5.0_16\bin目录(jdk安装目录下的bin目录)

java调用代码

 

代码

复制代码
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class test {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
ActiveXComponent dotnetCom = null;
dotnetCom = new ActiveXComponent(“TestCom.Encrypt”);
Variant var = Dispatch.call(dotnetCom,”GetEncrypt”,”哥是第一个参数”,”哥是第二个参数”);
String str  = var.toString(); //返回值
} catch (Exception ex) {
ex.printStackTrace();
}
}

}

复制代码

Shell特性

shell特性

可以通过打开或者关闭Bourne Again Shell的功能的方式来控制它的行为。不同的功能使用不同的方法开启和关闭。内置命令set控制着一组功能,而内置命令shopt控制另外一组命令。还可以调用bash在命令行中控制很多功能。

特性、选项还是变量?

提示 为了避免术语上的歧义,本书将用户可控制的shell的不同行为称为特性。bash info页面称之为“选项”和“控制可选shell行为的变量的值”。

1. set ±o:开启和关闭shell特性

通过使用-o或者+o选项,内置命令set(tcsh中有一个内置命令set,但是它的工作方式不同)可开启、关闭并列出某些bash特性。举例来说,下面的命令将开启noclobber特性:

 

$ set -o noclobber

 

使用下面的命令可以关闭这项特性(默认):

 

$ set +o noclobber

 

如果命令set -o不带任何选项,那么它将列出所有由set控制的每一项特性及其状态(开启还是关闭)。不带选项的命令set +o以一种特殊的形式列出了这些特性,用户可以依据它所给出的形式输入到shell中。表8-13列出了bash特性。

表8-13  bash特性

                 语法
allexport 在执行这条命令之后自动输出用户创建的所有变量和函数 set -o allexport set -a
braceexpand 使bash执行花括号扩展(默认) set -o

braceexpand

set -B
cdspell 纠正传递给cd的参数中目录名中小的拼写错误 shopt -s cdspell  
cmdhist 保存一个多行命令中的所有文本行,如果需要将添加分号 shopt -s cmdhist  
dotglob 使模糊文件引用中的shell特殊字符(通配符)来匹配以句号(.)开头的文件名;默认情况下,这些特殊字符并不匹配开头的句号;必须总要显式地指定文件名.和..,因为没有模式曾匹配它们 shopt -s dotglob  
emacs 为命令行编辑指定emacs模式(默认) set -o emacs  
errexit 使bash在遇到简单的命令失败(而不是控制结构)时退出 set -o errexit set -e
execfail 使shell脚本在找不到exec参数所指的文件时继续运行;默认情况下,当exec找不到其参数指定的文件时,脚本将终止 shopt -s execfail  

                                                                                                                                                         (续表)   

                用语 
expand_aliases 使别名扩展(默认情况下,对于交互式shell是开启的,而对于非交互式shell是关闭的) shopt -s

expand_alias

 
hashall 使bash记住它使用PATH找到的命令的位置 set -o hashall set -h
histappend 在shell退出时,使bash把历史列表追加到HISTFILE命令的文件后面;默认情况下,bash会覆盖掉这个文件 shopt -s

histappend

 
histexpend 使历史机制(使用感叹号)工作(默认);关闭这个特性将关闭历史扩展 set -o histexpand set -H
history 开启命令历史特性(默认情况下是开启的) set -o history  
ignoreeof 指定bash接收到10次EOF字符之后才能退出;在信号不好的链路上很有用 set -o ignoreeof  
monitor 启用作业控制(默认启用) set -o monitor set -m
nocaseglob 使模糊文件引用匹配文件名而不区分大小写(默认关闭) shopt -s

nocastglob

 
noclobber 帮助阻止文件覆盖(默认关闭) set -o noclobber set -C
noglob 关闭路径名扩展(默认关闭) set -o noglob set -f
notify 如果启用了作业控制,将立即报告后台作业的终结状态;默认行为是在显示下一个提示符之前显示该状态 set -o notify set -b
nounset 当在交互式shell中使用未设置变量时,将显示一条错误消息并退出shell脚本 set -o unset set –u
nullglob 使bask扩展模糊文件引用,这些模糊文件引用不能将文件名与一个空字符相匹配。默认情况下,bash无需扩展这些文件引用就可以传递它们 shopt-s nullglob  
posix 以POSIX模式返回bash set-o posix  
verbose 当bask读取命令行时显示这些命令行 set-o verbose set-v
vi 为命令行的编辑指定vi编辑模式 set-o vi  
xpg_echo 使内置命令cd在无需-e选项的情况下扩展反斜线转义序列 shopt –s xpg_echo  
xtrace 启用shell调试功能 set-o xtrace set-x

2. shopt:开启和关闭shell特性

内置命令shopt(shell option)开启、关闭和列出那些控制着shell行为的某些bash特性。举例来说,下面的命令将使bash在扩展模糊文件引用时,包含那些以句号(.)开头的文件名,-s表示设置:

 

$ shopt -s dotglob

 

通过下面的命令可将这项特性关闭(默认),-u表示取消设置:

 

$ shopt -u dotglob

 

如果只将特性的名称作为shopt唯一的参数,shell显示该特性是如何设置的:

 

$ shopt dotglob
dotglob          off

 

命令shopt不带任何选项或者参数时,将列出由shopt控制的那些特性及其状态。命令shopt -s不带参数时,将列出那些由shopt控制并设置为开启的特性。命令shopt –u将列出那些被取消或者关闭的bash特性。表8-13列出了bash特性。

使用shopt设置set ±o特性

提示 可以使用shopt设置或者取消那些由set ±o控制的特性。使用常规的shopt –s或者-u语法,并包含-o选项。举例来说,下面的命令将开启noclobber特性:

 

$ shopt –o –s noclobber

规范的Java Doc常用要点总结

Corba简介:Common Object Request Broker Architecture, 由OMG(Object Management Group)提出并逐步完善用来完成分布式通讯的架构。是一个分布式的面向对象应用架构规范, 它 定 义 了 分 布 式 对 象 如 何 实 现 互 操 作。

Corba的核心:ORB(Object Request Broker), CORBA对象的请求者不必知道它所请求的对象是在哪里,是如何实现的,而是由ORB来负责跨平台的运作管理, CORBA是一个中间件规范并不是一个实体软件。软件开发者通过使用第三方的ORB工具或IDL语言来定义CORBA对象,实现ORB功能。简单的说ORB就是用来连接网络上的不同对象。

Corba体系结构:

 

Corba调用流程:

  • Idl通过idl编译器分别在客户端和服务端生成idl stub和idl skeleton类
  • 首先客户端有一个interface引用,里面是idl声明的方法,当这个interface的方法被请求的时候会指向客户端的stub类,这个类实现了客户端的interface
  • stub利用ORB机制将请求带到服务端的对象,并通过ORB连接到的服务端,向服务端的Skeleton功能发送对象引用和参数
  • skeleton通过客户端的请求找到具体实现类的方法,调用后返回。

ORB连接是建立在TCP/IP标准之上的IIOP-Internet InterORB Protocol进行通信联系,相互传送信息

Corba的服务型访问模式:

 

服务端注册具体的service到相应的Nameservice中,客户端再到相应的Nameservice中查找

OMA定义的Corba四个组成部分:

  • 对象请求代理ORB
  • 对象服务(Object Services)

ü  名录服务(Naming Service)

ü  事件服务(Event Service)

ü  生命周期服务(Life Cycle Service)

ü  关系服务(Relationship Service)

ü  事务服务(Transaction Service)

  • 公共设施(Common Facilitites):向终端用户提供一组共享服务接口
  • Business Objects

Stub流程

 

POA 工作流程:

 

Corba Ramp up开发中遇到的问题和解决方案:

遇到的错误:

1 idl中interface name与module名字最好不能相同(即使大小写不同也不行),否则如果在eclipse里面用ORB Option插件进行compile的时候会出现编译错误,如果用jdk里面的idlj编译的话  即使interface name和module name相同也没有关系

2 如果出现classNotFound的exception原因可能为

(1)最好把jacorb/lib里面所有jar加入到环境变量classpath中

(2) 如果用eclipse等ide,需要把jacorb/lib里面的jar加入到build path的libraries里面

3 jacorb ns(nameservice)启动错误:找不到或无法加载主类 Files\Java\jdk1.7.0\lib;C:\Program

在设置环境变量java_home的时候路径中最好不能有空格,否则可能出现以上错误

4 在写server端代码,initial ORB的时候传入的Properties参数中设置的NameService路径很重要

props.put(“org.omg.CORBA.ORBInitRef.NameService”, “corbaloc::16.178.110.221:9527/NameService”);

jacorb/etc/jacorb.properties文件中ORBInitRef.NameService需要配置同样的路径,否则会出现(nameservice SEVERE Could not create initial reference for “NameService”)错误

ORBInitRef.NameService=corbaloc::16.178.110.221:9527/NameService

 

未遇到需要注意的错误:

5 在jacorb/etc/jacorb.properties文件中如要配置本地路径,尽量加上ORBInitRef.NameService=file:/c:/NS_Ref 而不是ORBInitRef.NameService=c:/NS_Ref

 

 

 

IDL语言:用来完成客户端对象和服务端对象之间的接口语言。IDL里面定义了要做的事情(就是方法),Server端完成方法的具体实现,Client可以根据IDL提供的信息向服务端发出请求,并且得到请求的结果。

1 Typedef: 用来定义module里面的全局变量

  • 定义数组:typedef sequence SomeBytes; — 这个sequence里面可以存储idl里面的任意类型
  • 定长数组:typedef sequence <long, 80> SomeBytes
  • 具体类型的数组:typedef sequence <long> SomeBytes
  • 无界类型:typedef string Description; — 表示Description没有长度约束
  • 有界类型:typedef string<15> Description; — 表示长度需要小于15

2 结构类型: struct, union, enum

  • Struct

struct StructName {

char charMember;

unsigned short AnotherMember;

};

结构里面最好不用typedef

  • Enum

enum Pet {cat, dog, fish, bird, rat, horse, gerbil};

  • Union

union MyUnion switch (char) {
case ‘a’:      string aValue;
case ‘b’:      long bValue;
case ‘c’:      boolean cValue;
default:       string defValue;
};

union虽然也是一个变量的集合,但他的作用的是一次只让一个变量可用。比如参数为a的时候,aValue将可用,其他的变量不可用

3 修饰符

  • Const – 定义常量
  • Unsigned – 加上这个修饰符后表示范围为正数,比如0-2的15次方,不加则是比如2的-15到2的15次方
  • Readonly – 属性只读,有点像java的final
  • Attribute – 用来定义interface里面的属性(interface里面的属性和方法默认都是public)
  • In, out, inout:用于interface里面的方法参数修饰符

In:就是传统的要传入server的参数;

  • out:可以被修改的参数

inout: 既可以被用作输入,又可以被修改

  • Oneway:因为方法调用在服务器对象处理调用时是阻塞的,function加上oneway后,在服务器没有返回结果之前方法不会被阻塞

4 idl中不能进行方法重载

5 接口可以包含类型定义

interface Example2 {

struct Example2Struct {

string Name;

long Value;

};

// …其它定义部分

};

如果在接口外要限定Example2Struct的范围,需要加上Example2::Example2Struct

6 exception:

IDL也有现成的异常,用户可以自定义异常

异常声明 exception GetAlarmList { string reason; };

抛出异常 raises (GetAlarmList),相当于java的throws异常声明

interface BankAccount {

double getAlarms() raises

(GetAlarmList);

};

7  Module外调用,比如AModule里面需要调用BModule里面的test方法,需要BModule::test

8 继承:

interface Desendant:Ancestor {

};

Interface支持多继承,但是继承的父接口里面不能有属性或者方法重复

每个接口隐含继承了Object Interface

9 接口的相互引用:

interface Example2; // forward reference

interface Example1 {

//definitions

readonly attribute Example2 TheOtherOne;

};

interface Example2 {

//definitions

Example1 ReturnTheOtherOne ();

};

需要有提前引用(要保证引用的interface在当前interface的后面),比如Example1和Example2出现相互引用的情况,就在Example1前面定义Example2,这样Example1就在Example2的后面。

10 数据类型

  • String, wstring区别
  • Any的变量可以接受任何数据类型

                    wstring是宽char,Unicode编码,一般情况下一个字符占两个字节大小

                    string是窄char,AscII编码,一个字符占一个字节大小

11 需要注意的事项:

  • IDL变量或者方法名定义不区分大小写,比如context,CONTEXT同时使用会有冲突
  • IDL中的属性生成java类后对应getter,setter,如果这个属性是readonly, java类中将没有任何getter, setter.

12 用idl生成java类

  • idlj –fclient hello.idl – 生产客户端java类
  • idlj – fserver hello.idl – 生成服务端java类
  • idlj -fall hello.idl – 生产客户端和服务端的类(默认不加fall就是这个效果)
  • idlj -oldImplBase hello.idl – 生成老版本的java类文件(jdk1.4以前)

生成的类列表(interface名字GoodDay):

  • client端:_GoodDayStub, GoodDay, GoodDayHelper, GoodDayHolder, GoodDayOperations
  • server端:  GoodDay, GoodDayOperations, GoodDayPOA

其中两端都有GoodDay, GoodDayOperations这两个接口,而这两个接口两端代码相同,具体就是idl接口里面定义相同的方法,客户端如果是java,就可以实现真正的暴露给客户端的java接口(如果是其他语言就是c#或者c++的接口,这样就实现了语言无关性),客户端看不到实现,通过接口对服务端发出请求,然后服务端通过如客户端提供的NameService的区域里面找到相应的服务端的接口的方法然后找到具体的实现,执行后把结果返回给客户端。

生成文件的具体分析:

  • GoodDay — CORBA 规范指出这个文件必须扩展 IDLEntity,并且与 IDL 接口同名
  • GoodDayOperations – 包含idl接口定义的方法,需要被GoodDay扩展
  • GoodDayHelper – 通过这个类的narrow静态方法把从NameService取到Corbar object转为更为具体的GoodDay接口
  • GoodDayHolder –为了需要通过引用来传递参数的任意数据类型而生成的(暂时没有用到todo)
  • GoodDayStub – 从代码可以看出这个类是和服务端通信的真正的桥梁
    • org.omg.CORBA.portable.OutputStream $out = _request (“hello_chinese”, true);  — 向服务端发起请求

$in = _invoke ($out);  – 得到请求结果

  • GoodDayPOA – 主要实现了通过服务端的一个探测功能,Stub发出请求的方法名,并且调用