Head First Java笔记(九)

远程部署的RMI

远程程序调用技术(Remote Metond Invocation )

当客户端调用远程对象的方法时,其实是调用代理商的方法,此代理被称为stub



客户端对象看起来像是在调用远程的方法,但实际上它只是在调用本地处理Socket和串流细节的“”“代理”


Java RMI提供客户端和服务器端的辅助设施对象。

使用RMI时,必须要决定协议:

JRMP:RMI原生的协议,它是为了Java对Java间的远程调用而设计的

IIOP:为了CORBZ(Common Object Request Broker Architecture)而产生的,能够调用Java对象或其他类型的远程方法。

在RMI中,客户端的辅助设施称为stub,而服务器端的辅助设施成为skeleton

stub是个处理低层网络细节的辅助性对象,它会把方法的调用包装起来送到服务器上。



创建远程服务

1.创建Remote接口(Server)

远程的接口定义了客户端可以远程调用的方法。它是个作为服务的多态化类。stub和服务都会实现此接口

2.实现Remote(Server)

真正执行的类。实现出定义在改接口上的方法。它是客户端会调用的对象。

3.用rmic产生stub与skeleton

客户端和服务器都有helper,你无需创建这些类或产生这些类的源代码,这都会在你执行JDK所附的rmic工具时自动地处理掉

4.启动RMI Registry

用户从此处取得代理(客户端的stub/helper对象)

5.启动远程服务

实现服务的类会起始服务的实例并想RMI registry注册。


1.创建远程接口

a.继承java.rmi.Remote

public interface MyRemote extends Remote{
b.声明所有的方法都会抛出RemoteException
import java.rmi.*;

pulbic interface MyRemote extends Remote{
        public String sayHello() throws RemoteException;
}
c.确定参数和返回值都是primitive主数据类型或Serializable

2.实现远程接口

a.实现Remote这个接口

public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{
    pulbic String sayHello(){
        return "Server says,'Hey'";
    }
    //more code
}
b.继承UnicastRemoteObject

c.编写声明RemoteException的无参构造函数

public MyRemoteImpl() throws RemoteException{ }
d.向RMI registry注册服务
try  {
        MyRemote service = new MyRemoteImpl();
        Naming.rebind("Remote Hello",service);
}  catch(Exception ex)   {...}

3.产生stub和skeleton

a.对实现出的类执行rmic

伴随JavaSdk而来的rmic工具会以服务的实现产生两个新类:stub和skeleton

%rmic MyRemoteImpl


4.执行rmiregistry

a.调出命令行来启动rmiregistry

&rmiregistry

5.启动服务

a.调用另一个命令行来启动服务

%java MyRemoteImpl


完整的代码

Remote Interface

import java.rmi.*;
public interface MyRemote extends Remote {
	//每个远程调用都会被认为是有风险的,throws RemoteException
	//远程方法的参数和返回这必须是primitive或Serializable的。
	public String sayHello() throws RemoteException;
}


Remote service

import java.rmi.*;
import java.rmi.server.*;
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {//创建远程对象最简单的方式:继承UnicastRemoteObject
	public String sayHello(){
		return "Server says, 'Hey";
	}
	
	//父类的构造函数声明了异常,所以你必须写出构造函数,
	//因为它代表你的构造函数会调用有风险的程序代码
	public MyRemoteImpl() throws RemoteException{}
	
	public static void main(String[] args){
		try{
			MyRemote service = new MyRemoteImpl();//创建出远程对象,
			Naming.rebind("Remote hello", service);//然后用静态的Naming.rebind()来产生关联,所注册的名称会供客户端查询
		} catch(Exception ex){
			ex.printStackTrace();
		}
	}
}

客户端如何取得stub对象?

使用RMI registry

MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/Remote Hello");



用户如何取得stub类?

最简单的情况:直接把类交给用户

更酷的方式:使用动态类下载(dynamic class downloading):stub对象会被加上注明RMI可以去哪里找到该对象的类围巾的URL标记。之后再解序列化的过程中,RMI会在本机上找不到类,所以就使用HTTP的Get来从该URL取得类文件。

完整的客户端程序代码

import java.rmi.*;
public class MyRemoteClient {
	public void go(){
		try{
			//MyRemote:客户端必须要使用与服务相同的类型,事实上 客户端不需要知道服务实际上的类名称
			//(MyRemote):必须转化成接口的类型,因为查询结果会是object类型
			//lookup()是个静态方法
			//127.0.0.1:主机名称或者ip地址
			//Remote Hello:必须要跟注册的名称一样
			MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/Remote Hello");
			
			String s = service.sayHello();
			
			System.out.println(s);
			
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	
	public static void main(String[] args){
		new MyRemoteClient().go();
	}
}

使用RMI时常犯的错误

1.忘记在启动远程服务前启动rmiregistry(使用Naming.rebind()注册服务前rmiregistry必须启动)

2.忘记把参数和返回类型做成可序列化

3.忘记将stub类交给客户端



servlet

servlet是放在HTTP Web服务器上面运行的Java程序,用来处理与用户交互的网页程序。
servlet可以使用RMI

创建并执行servlet的步骤
1.找出可以存放servlet的地方
2.取得servlets.jar并添加到classpath上
3.通过extends过HttpServlet来编写servlet类
4.编写HTML来调用servlet
5.给服务器设定HTML网页和servlet

简单的servlet
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class MyServletA extends HttpServlet {
	//一般的servlet会继承HttpServlet
	
	public void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException ,IOException {
		
		//告诉服务器和浏览器相应结果的形式
		response.setContentType("text/html");
		
		//此对象会给我们可写回结果的输出串流
		PrintWriter out = response.getWriter();
		
		String message = "If you're reading this ,it worked1";
		
		//我们的print对象是个网页
		out.println("<HTML><BODY>");
		out.println("<H1>" + message + "</H1>");
		out.println("</BODY></HTML>");
		out.close();
	}
}

连接到servlet的HTML网页
<HTML>
  <BODY>
    <a href="servlets/MyServletA">This is an amazing servlet.</a>
  </BODY>
</HTML>

JSP(Java Server Pages):实际上Web服务器最终会把JSP转换成servlet,但差别在于你所写出的是JSP。servlet让你写出带有HTML输出的类,而JSP让你写出带有JAva程序的网页。这样你就能在编写一般HTML网页的时候还能够同时掌握动态内容的能力,内嵌的程序代码可以于执行时处理。
jsp的好处在于能更容易地编写HTML而不会像servlet一样,出现一堆难以阅读的print命令。
jsp的另一个好处是将网页设计师与Java程序员的工作分离开来。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值