RMI远程访问:概述;相关概念;作用和意义;编程实例;Naming方法以及刚方法下的rebind

RMI概述
远程访问允许客户机访问别的计算机的对象和服务,就像这些对象服务在本地一样。
	远程访问是分布式应用的基础,这也是javaEE应用架构的基础之一。
java为远程访问提供了很好的简化,
	远程方法调用(Remote method Invocation,RMI)是java远程访问的重要规范之一,它允许本地java程序直接调用远程
1.RMI的相关概念
远程访问指网络中的一台计算机,可以使用另一台计算机的服务,
	对象或方法,效果就像使用本地的服务,对象和方法一样。通过远程访问,
	程序可以在物理位置不同的机器上运行,从而实现分布式计算
	
大型的企业及应用面临着更多的挑战;库存信息存储在一个过程中,订单系统又存储在另一个应用中,
	而客户信息则存储在第三个应用中,如果公司需要将这三个部分整合成一个系统,分布式开发则必不可少,因而必须使用远程服务。
		1.远程访问可以同多个计算单元的协同服务。数据库Server专门提供数据库服务,而Web服务器则专门提供Web服务,为了性能的优化,不同的逻辑计算单元会分布在不同的物理节点上,通过远程访问,可以是多个计算单元协同服务
		2.远程访问能提供更好的可用性和可靠性。计算机出现故障的可能性时刻存在,如物理故障,各种突发事件,或者系用的突然宕机,都会导致系统不可用。如果没有处于分布式应用中。某一物理节点出现问题,整个系统都不可用。但如果包含远程访问支持,出现问题的节点可以自动failover到另一个正常运行的节点上,从而保证整个系统的正常运行
		3.远程访问能提供更好的透明性。当一个节点访问另一个节点的方法或服务时,无需关心远程及访问的具体实现,远程节点的实现对于调用者完全透明
		4.远程访问能提供更好的开放性和可伸缩性。远程访问通常面向接口编程,远程服务只需向外提供服务接口,客户端的调用面向接口即可。因此,提供了更好的可伸缩性
		
RMI是纯java实现的,无需其他额外的支持,实现RMI调用的客户端程序被调用的方法,都是纯java代码,因此实现起来很简单、

在JDK1.5发布以前,读者需要手动rmic命令(位于JDK安装路径的bin路径下)来编译远程服务类,
	从而为远程服务类生成静态的sub和Skeleton类。在JDK1.5中采用了动态方式来自动生成Stub和Skeleton,从而简化了RMI编程
2.RMI的作用和意义
RMI可以说是java最早实现的远程访问技术,而且性能十分优秀,一直是其他JavaEE规范的实现基础。
	从JDK1.5开始,RMI已经得到了巨大的改进。作为java平台上性能最好的远程访问技术,
	RMI是java分布式架构的重要基础之一。掌握RMI的理论和编程方法,对于开发者更好地理解EJB等分布式组件的底层实现具有重要意义
	
不仅如此,由于RMI其实是对java Socket网络通信的高度封装,
	如果应用程序提供基于Socket的网络通信功能,这都可以考虑使用RMi来实现,
	当使用原生Socket进行网络编程时,有两个重要问题需要解决
		1.网络信息的交换问题:也就是需要采用合适的IO流进行网络读写,如果需要进行复杂的网络交换,往往还要封装自己的通信协议
		2.多线程问题:不管是服务器端的网络程序还是客户端的网络程序,仅有一条线程往往是不够的,因此开发者必须为两端的java程序提供多线程功能。编写多线程程序就不可避免的要处理线程同步,线程安全,死锁等棘手问题
		
对于需要提供基于Socket通信功能的程序,如果改为使用RMi来开发,上面两个问题就迎刃而解了。
	因为RMI对Socket通信进行了良好的封装,开发者可以直接在本地Java程序中调用远程java方法,
	而底层的Socket通信细节对开发者完全透明。不仅如此,由于RMI本身已经提供了多线程功能,
	因为开发者使用RMI进行开发也无需处理多线程那些繁琐的细节问题,从而可以大大简化开发的难度,而且可以提高开发效率。
3.RMI编程
从客户端和服务端入手
1.开发RMI服务器端程序
	RMI允许调用远程Java方法,因此我们需要先介绍编写RMI服务器,RMI需要通过远程接口"暴露"服务。
	也就是说。所有想被客户端调用的方法都必须在Remote接口里声明,否则无法完成调用。远程接口如下:
2.开发RMI客户端程序:
	由服务器端程序运行的时候时刻监听客户端程序来发出的访问请求,访问过后客户端就可以使用像本地的命令方式 去使用服务端程序

eg:
1.新建工程RMILession

借助面向对象进行数据的封装,封装到实体

2.创建Person类

public class Person implements Serializable {

	private String name;
	private int age;
	
	public Person() {
		
	}
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = 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;
	}
}

3.新建远程接口Server必须继承Remote接口

远程接口中声明的方法会通过网络传播,而网络又是不可靠的,
	因此,所有的远程方法都应该声明RemoteException异常来报告远程调用过程中的错误。
public interface Server extends Remote{

	String helloWorld(String name) throws Exception;
	
	Person getPerson(String name,int age) throws Exception;
}

4.服务器端:RMIServer变成远程调用 必须继承UnicastRemoteObject(远程对象转换)实现Server接口

public class RMIServer extends UnicastRemoteObject implements Server{

	protected RMIServer() throws RemoteException {
		super();
		// TODO Auto-generated constructor stub
	}

	@Override
	public String helloWorld(String name) throws Exception {
		// TODO Auto-generated method stub
		return name+"你好";
	}

	@Override
	public Person getPerson(String name, int age) throws Exception {
		// TODO Auto-generated method stub
		return new Person(name,age);
	}
	
	public void info() {
		System.out.println("本地方法");
	}

	//入口方法
	public static void main(String[] args) throws Exception {
		Server imp = new RMIServer();
		//本地端口注册:服务器在那个端口打开 注册服务启动所占用的端口号 不能使用已被使用的端口号 注册启动
		LocateRegistry.createRegistry(1099);
		/*Naming类提供在对象注册表中存储和获得远程对远程对象引用的方法,每个方法都可将某个名称作为一个参数
		 * 该名称是使用以下形式的URL格式(没有scheme组件)的java.lang.String
		 *		//host:port/name
		 *	一旦远程对象向本地主机上RMI注册表注册(绑定),远程(或本地)主机上的调用方可以通过名称查找远程对象
		 *获得其引用,并在该对象上调用远程方法,注册表可由在一个主机上运行的所有服务器共享,需要时个别服务器进程也可以创建和使用自己的
		 *注册表
		 *
		 *	rebind 提供对象注册表中存储和获取远程对远程对象引用方法
		 */
		Naming.rebind("rmi://:1099/crazy", imp);//重新绑定 绑定远程访问的对象
		//在rmi://:1099/crazy地址上绑定远程服务的对象imp,rmi限定,例如jdbc:mysql://localhost:3306/company	
		System.out.println("服务器等待连接");
	}

	@Override
	public List<Person> listPerson(String name, int age) throws Exception{
		// TODO Auto-generated method stub
		return null;
	}

}
如果有客户端进行连接方法调用,可以直接使用服务端的方法HelloWorld与getPerson

4.新建客户端RMIClient与服务端连接

public class RMIClient {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//不同主机不能使用new 远程调用 返回Remote 通过Naming类发现在URL地址上定义的对象
		Server ser = (Server) Naming.lookup("rmi://:1099/crazy");
		System.out.println(ser.helloWorld("Tom"));
		//服务器接收了一次客户端的连接访问结束,服务端不会自动结束掉
		System.out.println(ser.getPerson("Jim",20));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值