rmi服務
A. java RMI客戶端也要實現服務端的介面嗎
兩邊是通過介面來交換信息的,當然都需要介面和它的 Stub。
你做實驗時可以考慮創建3個項目:
1、介面項目,只包括介面和介面編譯後的 Stub 類
2、服務端項目,只包括伺服器類,它依賴介面項目。
3、客戶端項目,只包括客戶端,它依賴介面項目。
如果是從命令行運行它們,那麼服務端需要服務端項目和介面項目兩個 jar,客戶端需要客戶端項目和介面項目兩個 jar,我們需要面向介面編程減少耦合程度,不要把所有類全部放在同一個項目中編譯,將來會碰到很多麻煩事,比如包名太多就可能不支持 OSGi 這種方式。
在遠程調用類的應用中,使用靜態方法調用時一般需要介面類對應的Stub,我們 lookup 得到的其實是 Stub (它只包括了連接到伺服器的參數,然後把你想調用的」服務「 + 」參數「 發送給伺服器並將從伺服器返回的結果返回給客戶端程序,因此,它其實並沒有什麼」針對你的程序和伺服器的特殊特性),使用動態的調用方式就完全可以做到不需要特定的 Stub 而用一個通用的方式 (也就是 RMI 編譯生成的那個 Stub 類的內容我們來自己寫成一個框架。
上面一段是廢話,來說說怎麼配置環境測試它們。
客戶端項目中只需要有介面 TestServer 和 TestServerStub 兩個類,如果你的參數本身也是一個 Remote 子類,那麼參數類也需要有相應的 Stub。
另外,我們客戶端也可以僅自帶介面類而不自帶Stub,在運行的時候可以」請求從伺服器上下載一份 Stub",如下:
System.setSecurityManager(newRMISecurityManager());
然後在命令行添加額外參數:
-Djava.security.policy=$policy文件
-Djava.rmi.server.codebase=file:///C:/service-interface/classes/
這樣就可以啟用RMIClassLoader來自動從codebase對應的地方查找Stub類,這裡面codebase可以是一個Http或Ftp協議,注意這個codebaseURL後面一個/是必須的。那個$policy文件可以用JDKinpolicytool.exe來生成一個。
B. webService和RMI的區別
RMI的客戶端和服務端都必須是java,webservice沒有這個限制。
webservice是在http協議上傳內遞xml文本文容件,與語言和平台無關。
RMI是在tcp協議上傳遞可序列化的java對象,只能用在java虛擬機上,綁定語言
RMI是EJB遠程調用的基礎,僅用RMI技術就可以實現遠程調用,使用EJB是為了實現組件,事物,資源池,集群等功能。
WebService是通過XML來傳輸數據,可用http等協議因此可在異構系統間傳遞,並且可以穿過防火牆,可在公網上遠程調用
C. Java Rmi如何實現兩個客戶端之間的通信 求說的具體點
RMI的開發步驟
先創建遠程介面及聲明遠程方法,注意這是實現雙方通訊的介面,需要繼承Remote
開發一個類來實現遠程介面及遠程方法,值得注意的是實現類需要繼承UnicastRemoteObject
通過javac命令編譯文件,通過java -server 命令注冊服務,啟動遠程對象
最後客戶端查找遠程對象,並調用遠程方法
首先為服務建立一個Model層,注意因為此對象需要現實進行遠程傳輸,所以必須繼承Serializable
代碼
packagermi.model;
importjava.io.Serializable;
//注意對象必須繼承Serializable
{
privateintid;
privateStringname;
privateintage;
publicvoidsetId(intid){
this.id=id;
}
publicintgetId(){
returnid;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicStringgetName(){
returnname;
}
publicvoidsetAge(intage){
this.age=age;
}
publicintgetAge(){
returnage;
}
}
創建遠程介面PersonService,注意遠程介面需要繼承Remote
代碼
packagermi.service;
importjava.rmi.Remote;
importjava.rmi.RemoteException;
importjava.util.List;
importrmi.model.*;
//此為遠程對象調用的介面,必須繼承Remote類
{
publicList<PersonEntity>GetList()throwsRemoteException;
}
建立PersonServiceImpl實現遠程介面,注意此為遠程對象實現類,需要繼承UnicastRemoteObject
代碼
packagermi.serviceImpl;
importjava.rmi.RemoteException;
importjava.rmi.server.UnicastRemoteObject;
importjava.util.LinkedList;
importjava.util.List;
importrmi.model.PersonEntity;
importrmi.service.*;
//此為遠程對象的實現類,須繼承UnicastRemoteObject
Service{
publicPersonServiceImpl()throwsRemoteException{
super();
//TODOAuto-generatedconstructorstub
}
@Override
publicList<PersonEntity>GetList()throwsRemoteException{
//TODOAuto-generatedmethodstub
System.out.println("GetPersonStart!");
List<PersonEntity>personList=newLinkedList<PersonEntity>();
PersonEntityperson1=newPersonEntity();
person1.setAge(25);
person1.setId(0);
person1.setName("Leslie");
personList.add(person1);
PersonEntityperson2=newPersonEntity();
person2.setAge(25);
person2.setId(1);
person2.setName("Rose");
personList.add(person2);
returnpersonList;
}
}
建立伺服器端,在伺服器端注冊RMI通訊埠與通訊路徑,然後通訊javac命令編譯文件,通過java -server 命令注冊服務。以下面代碼為例,如果閣下將項目建立於D:\RMIRemotingService文件夾上時,則先輸入D:\RMIRemotingServicesrc>javac rmi/remotingservice/Program.java獲取Program.class(如何閣下使用的MyEclipse等開發工具,可跳過此步,直接在*/bin文件夾中直接調用已經生成的Program.class),然後輸入D:\RMIRemotingServicesrc>java rmi/remotingservice/Program啟動服務。
代碼
packagermi.remotingservice;
importjava.rmi.Naming;
importjava.rmi.registry.LocateRegistry;
importrmi.service.*;
importrmi.serviceImpl.*;
publicclassProgram{
publicstaticvoidmain(String[]args){
try{
PersonServicepersonService=newPersonServiceImpl();
//注冊通訊埠
LocateRegistry.createRegistry(6600);
//注冊通訊路徑
Naming.rebind("rmi://127.0.0.1:6600/PersonService",personService);
System.out.println("ServiceStart!");
}catch(Exceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
最後建立客戶端進行測試,注意客戶調用的RMI路徑必須伺服器配置一致
代碼
packagermi.remotingclient;
importjava.rmi.Naming;
importjava.util.List;
importrmi.model.PersonEntity;
importrmi.service.*;
publicclassProgram{
publicstaticvoidmain(String[]args){
try{
//調用遠程對象,注意RMI路徑與介面必須與伺服器配置一致
PersonServicepersonService=(PersonService)Naming.lookup("rmi://127.0.0.1:6600/PersonService");
List<PersonEntity>personList=personService.GetList();
for(PersonEntityperson:personList){
System.out.println("ID:"+person.getId()+"Age:"+person.getAge()+"Name:"+person.getName());
}
}catch(Exceptionex){
ex.printStackTrace();
}
}
}
常見錯誤
在命令提示符調用java命令時,顯示並無此命令。這是因為未在「環境變數」中綁定JAVA的JDK命令造成的,你首先單擊「計算機右鍵」->「屬性」->「高級」->「環境變數」。在系統變數Path設置中載入為JDK的路徑 .;D:Program FilesGenuitecCommoninarycom.sun.java.jdk.win32.x86_1.6.0.013in。然後在ClassPath載入伺服器端的Program.class地址 .;D:\RMIRemotingServicein
在調用javac命令時出現「javac 找不到文件 ..... 」此錯誤,可能是因為閣下輸入的文件路徑出現錯誤造成,注意不要把D:\RMIRemotingServicesrc>javac rmi/remotingservice/Program.java寫錯為D:\RMIRemotingServicesrc>javac rmi.remotingservice.Program.java
在調用D:\RMIRemotingServicein>java rmi/remotingservice/Program命令時出現「Exception in thread 'main' java.lang.NoClassEdfoundError」錯誤,第一這可能是閣下把Program錯寫為Program.class,注意java命令不需要加後綴名。第二可能是閣下把「java rmi/remotingservice/Program」錯寫為「java rmi emotingserviceProgram"。
D. 請教個問題基於RPC,RMI等遠程調用服務的事務怎麼保證強一致性要求。JTA能做到嗎
感測器來是一種檢測裝源置,能感受到被測量的信息,並能將感受到的信息,按一定規律變換成為電信號或其他所需形式的信息輸出,以滿足信息的傳輸、處理、存儲、顯示、記錄和控制等要求。
感測器的特點包括:微型化、數字化、智能化、多功能化、系統化、網路化。它是實現自動檢測和自動控制的首要環節。感測器的存在和發展,讓物體有了觸覺、味覺和嗅覺等感官,讓物體慢慢變得活了起來。通常根據其基本感知功能分為熱敏元件、光敏元件、氣敏元件、力敏元件、磁敏元件、濕敏元件、聲敏元件、放射線敏感元件、色敏元件和味敏元件等十大類。
E. java rmi怎樣實現伺服器間的通信
有幾個建議
1:主伺服器不用主動發IP給子伺服器(主伺服器不可能知道子伺服器的數目),也沒有必要主服務來發,完全可以讓子伺服器來主動向主服務索取IP。
2:結果完全沒有必要以文件形式存放(每次開機要重新獲得,沒有必要做持久化),完全可以存到一個Set中。
根據以上:我做一個簡單的實現:
***********************************************
IHost.java
package test.rmi.host;
import java.rmi.RemoteException;
/**
* remote interface
*
*/
public interface IHost extends java.rmi.Remote
{
void register(String ip) throws RemoteException;
String[] getAllSubServerList() throws RemoteException;
}
***********************************************
Host.java
package test.rmi.host.impl;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashSet;
import java.util.Set;
import test.rmi.host.IHost;
/**
*
* the implentation class of Ihost
*
*/
public class Host extends UnicastRemoteObject implements IHost
{
private static final long serialVersionUID = -2197983171132594422L;
private Set<String> subServers = new HashSet<String>();
public Host() throws RemoteException
{
super();
}
public String[] getAllSubServerList() throws RemoteException
{
String[] ips = new String[] {};
synchronized (this)
{
ips = subServers.toArray(ips);
}
return ips;
}
public void register(String ip) throws RemoteException
{
synchronized (this)
{
subServers.add(ip);
}
}
}
***********************************************
ServiceStartup.java
package test.rmi.host;
import java.rmi.Naming;
import test.rmi.host.impl.Host;
/**
* The main class for Host server,mainly for start up the host
*
*/
public class ServiceStartup
{
public static void main(String args[]) throws Exception
{
Host host = new Host();
Naming.rebind("HostServer", host);
}
}
***********************************************
SubServerStartup.java
package test.rmi.sub;
import java.net.InetAddress;
import java.rmi.Naming;
import test.rmi.host.IHost;
/**
* The main class for Sub server,mainly for start up the sub
*
*/
public class SubServerStartup
{
public static void main(String args[]) throws Exception
{
String hostIp = "";
IHost host = (IHost) Naming.lookup("rmi://" + hostIp + "/HostServer");
String myIp = InetAddress.getLocalHost().toString();
host.register(myIp);
//do something...
try{
//wait for other sub server start up
Thread.sleep(3000);
}catch(Exception e){}
String[] allSubServer = host.getAllSubServerList();
//do something...
}
}
***********************************************
本實現只是提供一個簡單的思路和基本的技術實現,希望可以幫助到你
以上代碼已經可以運行了,你說的具體點,是哪方面?是如何運行rmi程序嗎?
F. 在java RMI伺服器端是否可以寫多個介面,從而注冊多個不同的遠程對象呢
你想實現幾個介面都是可以的,只要符合遠程介面的規范
類似下面的代碼這樣寫啊
遠程介面實例
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote
{
String sayHello() throws RemoteException;
}
它定義了一個方法,sayHello,實現向調用者返回一個字元串
Server類
import java.rmi.registry.Resistry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server implements Hello
{
public Server(){}
public String sayHello()
{
return 「Hello,World!」;
}
public static void main(String args[])
{
Try{
Server obj=new Server ();
Hello stub=(Hello)UnicastRemoteObject.explortObject(obj,0);
//Bind the remote object』 s stub in the registry
Registry registry=LocateRegistry.getRegistry();
Registry.bind(「Hello」,stub);
System.err.println(「Server ready」);
}catch(Exception e)
{
System.err.println(「Server exception:」+e.toString());
e.printStackTrace();
}
}
}
G. rmi服務怎麼關閉
Namimg.unbind()不行嗎?
javadoc如下:
static void unbind(String name) 銷毀與遠程對象關聯的指定名稱的綁定。
而且樓主你為什麼要關內閉RMI服務呢?把伺服器關掉容RMI不就停止了嗎?
H. JavaRMI服務遠程方法調用漏洞如何修復lin
Linux的Apache或WebLogic應用被檢測出這個漏洞,NSFOCUS(綠盟)給出的解決辦法是:
臨時解決方法:【限制訪問或刪除類文件】
如果您不能立刻安裝補丁或者升級,建議您採取以下措施以降低威脅:
* 使用防火牆規則及文件系統訪問限制
* 使用 SerialKiller 替換進行序列化操作的 ObjectInputStream 類
* 刪除掉項目里的「commons-collections-3.2.jar///org/apache/commons/collections/functors/InvokerTransformer.class」 文件,刪除後項目可能會在某些功能下報錯。
安裝廠商補丁:【下載3.2.2以上版本commons-collections補丁】
目前廠商已經發布了升級補丁ACC 3.2.2 以修復這個安全問題,請到廠商的主頁下載:
Download Commons Collections
http://svn.apache.org/viewvc?view=revision&revision=1713307
https://blogs.apache.org/foundation/entry/apache_commons_statement_to_widespread
I. java RMI如何停止伺服器。
為了以編程方式啟動RMI注冊,你可以使用LocateRegistry.createRegistry(int port)方法。該方法返回類型注冊的一個對象。當我們想在應用程序一端終止這個注冊時,我們保存這個參考。就在我們啟動我們的在JMXAgent.start()中的JMXConnectorServer之前,我們首先啟動RMI注冊,使用下列代碼行:
registry = LocateRegistry.createRegistry(Constants.RMI_REGISTRY_PORT);
在應用程序一端,在JMXAgent.stop()中停止JMXConnectorServer之後,調用下列方法來終止該注冊:
UnicastRemoteObject.unexportObject(registry,true);
http://www.webjx.com/htmldata/2006-03-27/1143443474.html