在當前Java開發中,Web佔據很大空間, 10個Java程序員就至少有6個是搞Web方面開發的,但不管是C/S還是B/S, 軟件最終的目的只有一個,那就是對各種服務的集成. 在軟件技術發展到今天,EIS的集成出現了2大主流,即SUN的J2EE(JavaEE)方案和MS的.NET方案,他們要作的都是將不同的服務進行集成後統一接口暴露給客戶端,比如在J2EE裏,實現對分佈環境下服務的集成---RMI等,傳統的CORBA等,以及.NET的remoting等,當然我們這裏只討論Java的集成方案.
在J2EE集成中,集成大體分爲2中,第一是Java系統之間的集成,另外一個是Java與其他語言開發的信息系統之間的集成.下面分開討論.
第一: Java系統之間的集成: 該情況下集成比較簡單,只要雙方提供服務接口即可,比如服務方提供RMI遠程接口或者直接以EJB的形式把接口暴露給客戶端,在這中情況下,最核心的部分就是RMI,應爲EJB也是架設在RMI基礎之上的一個規範,下面簡要介紹RMI的數據流原理以及給出一個開發實例:
RMI開發分爲2個部分,一個是服務器端開發,一個是客戶端開發,服務器端提供遠程業務接口以及服務實現,而客戶端需要提供和其想匹配的遠程業務接口和Stub存根,在此需要特別說明的是,客戶端的遠程接口和服務器端的遠程接口一定要具有相通的SerialUID,否則他們是無法通信的,在這裏我詳悉說明下Java對象在網絡上傳輸的原理:
如果一個對象需要在網絡上傳輸,它一定是一個可序列化的,這個我想幾乎所有Java程序員都知道,實現java.io.Serializable接口即可,但通信雙方,一邊將該對象發出去,另外一邊就必需用該類進行接收,我們要作的就是分別把這個dto打2個jar包,一個放到服務器端,一個放到客戶端 ,這樣它們就能通信, 這裏我們作一個實驗,你第一次編譯的時候(javac),把生成的class打到jar包裏,然後再javac一次,把class打包到另外一個 jar包裏,分別把這2個jar包放到客戶端和服務器端, 運行程序,你會發現會出現序列號不一致的文體, 讀者肯定會問這是爲什麼? 原因就是這2個類不一樣,應爲根據java規範,可許列化的類,必需提供一個private static final long serialUID 這個Field, 我們可以在程序裏 顯式 設置,如果不顯式 設置, javac在編譯源代碼的時候會自動生成一個放到class文件裏 (不信你javap下看看),正是由於2次javac產生的隨機serialUID不一致,所以才造成了剛剛上面的哪個錯誤出現,現在解決的辦法有2個,第一是 只javac一次,把同一個 class打2 次包, 分別給客戶端和服務端,第2是顯式指明serialUID在代碼裏,這樣即時javac N次也不要緊. }
現在繼續講RMI , 當用戶調用客戶端遠程接口的時候,比如:Naming.lookup("rmi://192.168.0,1//serviceName")的時候,JVM會察覺到這是一個RMI請求,這時它會把這個路由信息(192.168.0.1/serviceName)通知給Stub,而Stub就負責向遠程服務器的RMI 中央註冊機發送請求,中央註冊機調用服務通過這個服務名子(serviceName)來找到註冊進來的對象實例,這時候調用這個實例來處理,完了返回值按原路逆向返回,接收端進行反序列話, (注: 序列化和反序列化的任務都是由 2 端的Stub和框架完成的).這樣一個遠程調用過程就完成了,下面代碼說明:
A. 創建一個遠程接口: Mclaren.java
package org.mclaren.remote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Mclaren extends Remote {
public String sayHello(String name) throws RemoteException;
}
B. 創建一個服務實現: MclarenService.java
package org.mclaren.remote;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.rmi.Naming;
public class MclarenService extends UnicastRemoteObject implements Mclaren {
public MclarenService() throws RemoteException {
super();
}
public void registerService(String serviceName) {
try {
//綁定名稱後註冊到中央註冊機
Naming.rebind(name,this);
System.out.println("服務已經起動");
} catch(Exception e) {
e.printStackTrace();
}
}
public String sayHello(String name) throws RemoteException {
return "Hello :"+name+" this is processed by RMI service":
}
}
C. 編寫服務起起動類: StartUp.java
package org.mclaren.remote;
import java.rmi.RMISecuriryManager;
public class StartUp {
public static void main(String[] args) {
try {
System.setSecurityManager(new RMISecurityManager());
MclarenService mclaren = new MclarenService();
mclaren.registerService("//MclarenService");
} catch(Exception e) {
e.printStackTrace();
}
}
}
D. 編寫安全策略文件 mclaren.policy
grant {
Permission java.security.AllPermission ("192.168.0.2,192.168.0.3","");
};
註解: 這段話的意思是 允許 192.168.0.2,192.168.0.3這2個機器的任意端口使用本服務作任何事情,當然你可以改 .
E. 爲服務作準備: 打開cmd 或者 終端(Linux),到JDK_HOME/bin 下執行 rmiregistry明令起動RMI中央註冊機 ( rmiregistry的語法是: rmiregistry <端口> ,默認爲1099).
到剛哪個工程的classes下,執行明令: rmic org.mclaren.remote.MclarenService 來生成客戶端 Stub,然後把stub和遠程接口一起打包成client.jar文件:
F. 起動服務: 假設: 我們工程的類輸出目錄在: F:/RMITest/classes下,而mclaren.policy 在F:/RMITest下 .那麼在cmd裏執行:
java -classpath F:/RMITest/classes org.mclaren.remote.StartUp -Djava.rmi.server.codebase=file:///F://RMITest//classes/ -Djava.security.policy=file:///F://RMITest//mclaren.policy
完了後會發現輸出: 服務已經起動
現在開發客戶端: 把client.jar導進來
public class Client {
public static void main(String[] args) {
try {
Mclaren mclaren = (Mclaren) Naming.lookup("rmi://192.168.0.1:1099//MclarenService");
mclaren.sayhello("mclaren");
} catch(Exception e) {
e.printStackTrace();
}
}
}
執行後會 出現 : Hello : mclaren this is processed by RMI service"
對於EJB就沒這麼複雜了,大家自給看書,下面將Java如何與C/C++進行集成.
A. Java調用C++: Java 調用C++,就得用JNI接口,關於JNI的概念我就不多廢話了,自己去so,(在國內別的不好着,找概念的東西還是一找一堆). 下面舉例子:
(1) 首先創建一個Java文件: Mclaren.java
package org.mclaren.jni;
public class Mclaren {
static {
System.loadLibrary("Mclaren'); // load Dll or so
}
public native void sayHello(String name);
}
(2) 生成頭文件: 在classes目錄下輸入: javah org.mclaren.jni.Mclaren 會生成一個C的頭文件 org_mclaren_jni_Mclaren.h
(3) 新建一個VC工程,把 %JAVA_HOME%/include 和 %JAVA_HOME%/include/win32添加到include裏,或者直接把jni.h 和jni_md.h copy過來也可以 ,然後新建一個cpp文件 Mclaren.cpp(我採用C++寫 ) ,這樣你VC工程目錄下將含有4個文件: jni.h, jni_md.h. org_mclaren_jni_Mclaren.h, Mclaren.cpp
其中Mclaren.cpp內容爲:
#include <iostream>
#include "org_mclaren_jni_Mclaren.h"
using namespace std;
JNIEXPORT JNICALL org_mclaren_jni_Mclaren_SayHello(
JNIEnv * env, jobject obj, jstring name) {
char *str = (char *) name;
cout<<"C++輸出 :"<<str<<endl;
delete str;
}
將上面的工程打包成一個dll後放到硬盤上任意地方,假設D://lib//Mclaren.dll, 我們只要把這個dll放到程序的運行時 librarypath 裏就可以 .
下面編寫測試類:
public class Test {
public static void main(String[] args) {
Mclaren mclaren = new Mclaren();
mclaren.sayHello("Mclaren");
}
}
假設這個工程的 classes目錄是: F://JNIJ2C/classes
那麼: java -classpath F://JNIJ2C/classes Test -Djava.library.path=D://lib//Mclaren.dll
這時會輸出: C++輸出 Mclaren.
B. C++ 調用Java: C++調用Java的時候,就需要用C++來起動Java虛擬機,來裝載類,下面我分別在Windows環境下和Linux環境下講述:
(1) Windows環境下:
a. 新建一個C++工程(不需要支持MFC), 把JAVA_HOME/include/jni.h JAVA_HOME/include/win32下的 jni_md.h copy 到C++工程目錄下,然後把 JAVA_HOME/jre/bin/client/jvm.dll 寫進系統PATH ,再把JAVA_HOME/lib/jvm.h 添加到VC的工程lib裏.
b. 新建Mclaren.cpp ,內容如下:
#include "jni.h"
#include <iostream>
using namespace std;
int main() {
JNIEnv *env;
JavaVM *jvm;
JavaVMOption options[3];
JavaVMInitArgs args;
memset(&args,0,sizeof(&args),)
args.version = JNI_VERION_1_4;
args.nOptions = 3;
args.option = options;
args.ignoreUnrecognized = JNI_TRUE;
options[0] = "-Djava.class.path=.";
options[1] = "-Djava.library.path=.";
options[2] = "-verbose:jni";
int ret = JNI_CreateJavaVM(&jvm,(void **)&env,&args);
if(ret < 0) {
cout<<"起動JVM 失敗"<<endl;
return -1;
}
//我們加載上面的RMI Client類
jclass cla = env->FindClass("org/mclaren/remote/Client");
//取得 main方法, 第3個參數是Java簽名
jmethodID init = env->GetStaticMethodID(cla,"main","([-Ljava.lang.String)V");
env->CallStaticMethod(cla,init,NULL);
jvm->DestroyJavaVM();
return 0;
}
VC編譯後,執行. 取得的效果和用java.exe起動是一樣
(2) Linux環境下 :
a. 代碼不變,因爲上面用的是標準C++ 庫
b. 設置好環境變量JAVA_HOME, CLASSPATH和 PATH
c. 在 .bash_profile裏追加一條:
export LD_LOBRARY_PATH=$JAVA_HOME/jre/lib/i386/client
到Mclaren.cpp所在的目錄下輸入命令 :
g++ -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -L $LD_LIBRARY_PATH -o Mclaren Mclaren.cpp -ljvm
注意" -ljvm是小寫的L
這樣就會產生一個Mclaren的可執行文件,執行一下,效果同上.
J2EE信息系統集成解決方案
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章
在VMware中裝jkd,oracle總結
又一次在VM中重新開始安裝linux操作系統啦,這一次要把步驟全都記下來,以便以後需要時使用 1:目的 我的目的是在VM中建兩個linux操作系
iteye_8905
2020-06-17 05:07:57
對Java Generic相關知識的總結
luedipiaofeng
2020-02-20 20:46:10
將自行添加的包編譯進Tomcat
38734603
2019-02-22 22:50:04
關於單元測試的學習及其工具
sys53
2018-09-03 16:13:06
詳解spring2.0的scope
luedipiaofeng
2018-09-01 20:23:05
Hibernate 2與Hibernate 3的區別
luedipiaofeng
2018-09-01 20:23:05
國內Java四大山頭初現
luedipiaofeng
2018-09-01 20:23:05
國外著名java站點
luedipiaofeng
2018-09-01 20:23:05
Choosing among JCA, JMS, and Web services for EAI
luedipiaofeng
2018-09-01 20:23:04
JPA學習總結
luedipiaofeng
2018-09-01 20:23:04
JAVA:Filter編碼器
luedipiaofeng
2018-09-01 20:22:58
在JAR包裏讀取配置文件
iteye_8905
2018-09-01 07:38:21
java用For循環Map
iteye_8905
2018-09-01 07:38:20
IBATIS 常用寫法
iteye_8905
2018-09-01 07:38:18