天天看點

java RMI 簡單應用

一、Java RMI簡介

Java RMI(Remote Method Invocation,遠端方法調用),允許運作在一個Java虛拟機的對象調用運作在另一個Java虛拟機上的對象的方法。在RMI中的核心是遠端對象(remote object),除了對象本身所在的虛拟機,其他虛拟機也可以調用此對象的方法,而且這些虛拟機可以是運作在網絡上的不同計算機中。

1、1 RMI原理

RMI是基于遠端消息交換協定JRMP( Java Remote Method Protocol)協定通信,這個協定類似于HTTP協定,規定了用戶端和服務端通信要滿足的規範。JRMP是專為Java的遠端對象制定的協定,由于JRMP是專為Java對象制定的,是以,RMI對于用非Java語言開發的應用系統的支援不足。不能與用非Java語言書寫的對象進行通信(意思是隻支援用戶端和伺服器端都是Java程式的代碼的遠端調用)。Java RMI通信模型如下圖所示:

java RMI 簡單應用

RMI遠端調用步驟:

1,客戶調用用戶端本地對象stub上的方法

2,用戶端對象stub封裝好調用資訊,然後通過網絡發送給服務端對象skeleton

3,服務端對象skeleton将用戶端對象發送來的調用資訊解析,然後找對正在調用的對象及方法。

4,執行對應方法,然後将結果傳回給服務端對象skeleton

5,服務端對象将結果傳回給用戶端對象Stub。

6,用戶端對象将傳回結果傳回給調用者

二、Java RMI代碼實作

2、1簡單Java代碼實作

服務端:

1、建立實體類

public class User implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public String toString() {
		return "User [name=" + name + ", age=" + age + "]";
	}
	
	
}
           

這個類需要實作Serializable接口,用于資訊的傳輸。

2、服務端遠端接口定義

public interface RmiService extends Remote{

	public String getUserInfo ()throws RemoteException;
	
	public String getName() throws RemoteException;
}
           

接口必須繼承Remote類,每一個定義地方法都要抛出RemoteException異常對象。

3、接口具體實作類定義

public class RmiServiceImpl extends UnicastRemoteObject implements RmiService{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	

	public RmiServiceImpl() throws RemoteException {
		super();
	}

	@Override
	public String getUserInfo() throws RemoteException {
		// TODO Auto-generated method stub
		User user = new User();
		user.setName("張三");
		user.setAge(18);
		return user.toString();
	}

	@Override
	public String getName() throws RemoteException {
		// TODO Auto-generated method stub
		return "李四";
	}
}
           

這個類需要實作上面的接口,還需要繼承UnicastRemoteObject類和顯示寫出無參的構造函數。

4、建立啟動類啟動服務

public static void main(String[] args) throws RemoteException,NamingException{
		// TODO Auto-generated method stub

		
		RmiService service = new RmiServiceImpl();
		
		Registry registry = LocateRegistry.createRegistry(1099);
		
		registry.rebind("service", service);
		//或者使用下列的
		/*try {
			Naming.rebind("rmi://127.0.0.1:1099/service", service);
			//Naming.rebind("service", service);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	    System.out.println(" rmi server is ready ...");
	}
           

用戶端:

1、将服務端的實體類以及遠端接口(User和RmiService )打成jar包導入到用戶端程式中,然後建立用戶端程式進行調用。

public static void main(String[] args){
		RmiService service;
		try {
			Registry registry = LocateRegistry.getRegistry("localhost",1099);
			service = (RmiService)registry.lookup("service");
			//service = (RmiService)Naming.lookup("service");
			//service = (RmiService)Naming.lookup("rmi://127.0.0.1:1099/service");
			System.out.println(service.getUserInfo());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
           

2.2、在spring中配置Java RMI

服務端:

1、定義實體類(和上面類似)

public class User implements Serializable {

	
	private static final long serialVersionUID = 1L;
	
	private String name;
	private int age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return name+age+"歲!";
	}
	
	
}
           

需要實作Serializable接口

2、定義遠端接口

public interface RMIService {

	public String getUserInfo();
}

           

和上面不同的是這是一個普通的接口,不需要繼承其他接口

3、定義接口實作類

public class RMIServiceImpl implements RMIService{

	private User user;
	@Override
	public String getUserInfo() {
		// TODO Auto-generated method stub
		return user.toString();
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}

	
}
           

隻需實作遠端接口即可,不需要其他操作

4、配置spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"  
    xsi:schemaLocation="  
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd  
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">  
  
  <bean id="rMIServiceImpl" class="com.test.service.impl.RMIServiceImpl">
     <property name="user" ref="user"/>
  </bean>
  
  <bean id="user" class="com.test.bean.User" >
     <property name="name" value="張三"/>
     <property name="age" value="19" />
  </bean>
  
   <!-- 定義服務端接口 -->
    <bean class="org.springframework.remoting.rmi.RmiServiceExporter">
        <!-- 将遠端接口實作類對象設定到RMI服務中 -->
        <property name="service" ref="rMIServiceImpl" />
        <!-- 設定RMI服務名,将作為RMI用戶端的調用接口-->
        <property name="serviceName" value="rmiservice" />
        <!-- 将遠端接口設定為RMI服務接口 -->
        <property name="serviceInterface" value="com.test.service.RMIService" />
        <!-- 為RMI服務端遠端對象系統資料庫設定端口号-->
        <property name="registryPort" value="9090" />
    </bean>
</beans>  
           

5、建立啟動類啟動RMI服務

public static void main(String[] args) {
		// TODO Auto-generated method stub

		ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
		System.out.println("RMI啟動成功!");
	}

           

啟動成功截圖

java RMI 簡單應用

用戶端:

1、将服務端的實體類以及遠端接口(User和RmiService )打成jar包導入到用戶端程式中

2、配置服務端spring配置。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"  
    xsi:schemaLocation="  
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd  
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">  
  
  <!--bean id為程式調用時輸入的第一參數-->    
    <bean id="rmiservice" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> 
        <!--ip和端口為server的ip和剛才注冊的端口号,服務名為設定的serviceName-->
        <property name="serviceUrl" value="rmi://localhost:9090/rmiservice"/>
        <!--調用的接口-->
        <property name="serviceInterface" value="com.test.service.RMIService"/>
        <!-- 當連接配接失敗時是否重新整理遠端調用stub -->
        <property name="refreshStubOnConnectFailure" value="true"/>
    </bean>
</beans>  
           

3、建立用戶端程式調用RMI服務

public static void main(String[] args) {
		// TODO Auto-generated method stub

		ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
		RMIService rmiservice = (RMIService)ctx.getBean("rmiservice");
		System.out.println(rmiservice.getUserInfo());
	}

           

傳回結果。

java RMI 簡單應用