RMI是Remote Method Innovation的缩写,表示远程方法引进。
为不同机器之间提供服务。
第一步:定义接口。这个接口既是自己实现需要,也是远程需要的。两者定义应该是一样的。
package com.xiva.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* @Description 接口必须扩展Remote接口,其方法必须throws RemoteException
* @author Administrator
*
*/
public interface RoomService extends Remote{
public String getRoomName(Long roomId) throws RemoteException; ;
}
第二步:实现接口。实现接口并写一个main方法启动服务。
package com.xiva.rmi;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
/**
* @Description 需要extends UnicastRemoteObject类
* @author Administrator
*
*/
public class RoomServiceImpl extends UnicastRemoteObject implements RoomService {
protected RoomServiceImpl() throws RemoteException {
super();
}
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public String getRoomName(Long roomId) throws RemoteException{
if(Long.valueOf(12l).equals(roomId)){
return "废之间";
}
return "天之间";
}
public static void main(String[] args) {
// System.setProperty("java.security.policy","*.policy");//设置安全策略
System.setSecurityManager(new RMISecurityManager());
try {
Registry reg = LocateRegistry.createRegistry(2011); //注册服务端口
RoomServiceImpl pt = new RoomServiceImpl();
reg.rebind( "RoomService" , pt); //绑定服务名称
System.out.println("Ready to do time");
} catch(Exception e) {
e.printStackTrace();
}
}
}
写好上面程序,就可以使用java来运行这个类了。
第三步,编写客户端程序。
package com.xiva.rmi.client;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import com.xiva.rmi.RoomService;
public class CallRoom {
public static void main(String[] args) {
System.setSecurityManager( new RMISecurityManager());
try {
RoomService t = (RoomService)Naming.lookup( "rmi://192.168.0.16:2011/RoomService");
System.out.println(t.getRoomName(11l));
} catch(Exception e) {
e.printStackTrace();
}
}
}
当然写完这些程序,在一般情况下是可以运行的。比如我的机器就可以正常运行。
但是有时我们是还需要指定keystore的,主要与环境有关系。有的计算机某些端口访问是需要提供验证,一般部署环境都是这样。
相关安全策略的设置:
D:\Program Files\Java\jdk1.6.0_29\jre\lib\security\java.policy
// Standard extensions get all permissions by default grant codeBase "file:${{java.ext.dirs}}/*" { permission java.security.AllPermission; }; // default permissions granted to all domains grant { // Allows any thread to stop itself using the java.lang.Thread.stop() // method that takes no argument. // Note that this permission is granted by default only to remain // backwards compatible. // It is strongly recommended that you either remove this permission // from this policy file or further restrict it to code sources // that you specify, because Thread.stop() is potentially unsafe. // See the API specification of java.lang.Thread.stop() for more // information.stopThread // permission java.lang.RuntimePermission "accessClassInPackage.sun.jdbc.odbc"; permission java.lang.RuntimePermission "stopThread"; permission java.lang.RuntimePermission "modifyThreadGroup"; permission java.lang.RuntimePermission "modifyThread"; permission java.net.SocketPermission "*", "connect,accept,resolve"; // allows anyone to listen on un-privileged ports permission java.net.SocketPermission "localhost:1024-", "listen"; // "standard" properies that can be read by anyone permission java.util.PropertyPermission "java.version", "read"; permission java.util.PropertyPermission "java.vendor", "read"; permission java.util.PropertyPermission "java.vendor.url", "read"; permission java.util.PropertyPermission "java.class.version", "read"; permission java.util.PropertyPermission "os.name", "read"; permission java.util.PropertyPermission "os.version", "read"; permission java.util.PropertyPermission "os.arch", "read"; permission java.util.PropertyPermission "file.separator", "read"; permission java.util.PropertyPermission "path.separator", "read"; permission java.util.PropertyPermission "line.separator", "read"; permission java.util.PropertyPermission "java.specification.version", "read"; permission java.util.PropertyPermission "java.specification.vendor", "read"; permission java.util.PropertyPermission "java.specification.name", "read"; permission java.util.PropertyPermission "java.vm.specification.version", "read"; permission java.util.PropertyPermission "java.vm.specification.vendor", "read"; permission java.util.PropertyPermission "java.vm.specification.name", "read"; permission java.util.PropertyPermission "java.vm.version", "read"; permission java.util.PropertyPermission "java.vm.vendor", "read"; permission java.util.PropertyPermission "java.vm.name", "read"; permission java.util.PropertyPermission "file.encoding", "read"; };
设置为上面安全策略。
createRegister后,可以使用RMIGetRegister 来获取registry,bind新的服务名
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.xiva; import java.rmi.AlreadyBoundException; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; /** * * @author Administrator */ public class RMIGetRegister { private static Registry registry = null; private static String bindName = "RoomService"; public static void main(String[] args) throws InterruptedException, RemoteException, AlreadyBoundException { // 取得RMIRegistry try { registry = LocateRegistry.getRegistry(2012); } catch (RemoteException ex) { System.out.println(ex.getMessage()); } // 解除Registry绑定 try { System.out.println("trying to unbind rmi registry"); registry.unbind(bindName); Thread.sleep(3000); //wait 3 seconds. } catch (RemoteException ex) { ex.printStackTrace(); } catch (NotBoundException ex) { //nothing to do } RoomService o = new RemoteServiceImpl(); //RemoteMethod stub= (RemoteMethod) UnicastRemoteObject.exportObject(o, 0); registry.bind("xiva", o); System.out.println("bindName"); } }
注意UnicastRemoteObject.exportObject(o, 0)其中的o是没有extends UnicastRemoteObject的类。