java基础十一[远程部署的RMI](阅读Head First Java记录)

方法的调用都是发生在相同堆上的两个对象之间(同一台机器的Java虚拟机),如果想要调用另一台机器上的对象,可以通过Socket进行输入/输出。

远程过程调用需要创建出4种东西:服务器、客户端、服务器辅助设施、客户端辅助设施

RMI

Java的JMI提供客户端和服务器端的辅助设施对象(stub和skeleton,现在实际只用stub文件,客户端和服务端用一个)

辅助设施是实际执行通信的对象,他会让客户端感觉在调用本机,实际上辅助设施类似于代理,将客户端传送的信息通过Socket连接发送给服务端辅助设施,然后服务端辅助设施解包调用真正的服务端的服务,服务辅助设施取得结果后将他通过Socket连接返回给客户端辅助设施,客户端辅助设施解开这些信息传给客户端

远程的服务调用是通过java.rmi.registry来实现的。它提供了RMI注册表的一个类和两个接口,注册表绑定字符串名称和远程对象,可以通过注册表调用远程服务的某个对象

服务器端的service实现了远程调用的真正方法

Client辅助设施和Service辅助设施是同一个文件,在服务器端生成的

创建远程服务

大致步骤如下图所示:

 

步骤1:创建Remote接口

定义客户端会调用的方法,stub和服务都会实现此接口。远程接口定义了客户端可以远程调用的方法。

import java.rmi.*;

public interface MyRemote extends Remote{

public String sayHello() throws RemoteException;

}

说明:

1.接口必须继承Remote

2.远程调用是有风险的,需要通过抛出一个RemoteException异常强迫客户端注意到这件事

3.远程方法的参数和返回值必须是primitive或Serializable的

步骤2:实现Remote接口

这个是真正执行的类,实现接口上的方法,也是客户端会调用的对象,去执行真正的工作

public class MyRemoteImp1 extends UnicastRemoteObject implements MyRemote{

public MyRemoteImp1() throws RemoteException{}//UnicastRemoteObject会抛出RemoteException异常,构造函数抛出同样异常

public String sayHello(){//实现Remote接口的所有方法

return "Server says,‘Hey’"

}

}

说明:

1.实现Remote的接口

2.要有与远程有关的功能,可以继承UnicastRemoteObject(UnicastRemoteObject 会抛出RemoteException异常,如果调用需要构造函数也抛出同样的异常)

3.向RMI registry注册服务

只有向RMI registry注册了,才能让远程用户存取(一定要RMI registry一定要注册起来否则运行程序会失败),注册对象时RMI 会把stub加到registry中,这是客户端需要的,使用java.rmi.Naming的rebind()注册服务

try{

MyRemote service=new MyRemoteIm1();

Naming.rebind("Remote Hello",service);//将实现的接口类实例向RMI registry注册,帮服务命名(Remote Hello)

}catch(Exception ex){...}

步骤3:用rmic产生stub

对真正实现的类执行rmic,产生helper类(stub)

会按照命名规则在远程实现的名称后加上_Stub。

rmic MyRemoteImp1

会生成MyRemoteImp1_Stub.class文件

步骤4:启动RMI registry(rmiregistry)

用户会从此处获得代理(客户端的sub/helper对象)

需要在实现的服务类下去执行命令:rmiregistry

如果想指定端口号,可以通过【rmiregistry 端口号】来启动

步骤5:启动远程服务

【java 真正实现的类】启动服务,实现服务的类的实例会向RMI registry注册(注册后才能对用户提供服务)

java MyRemoteImp1

指定服务端口号

两种方法:一是程序中指定,二是启动rmiregistry时指定

程序中指定:

启动rmiregistry指定:【rmiregistry 端口号】

客户端实现

客户端获得stub对象

直接将服务器上生成的stub文件拷贝到客户端上即可

客户端调用远程方法

通过Naming.lookup()的静态方法寻找某台IP上注册的远程方法(通过Naming.rebind()注册),返回一个stub对象

MyRemote service=(MyRemote) Naming.lookup("rmi://127.0.0.1:服务端口号/Remote Hello");

如果Naming.lookup没有指定服务的端口号,则用java默认的1099端口号

说明:

1.客户端调用服务必须与服务端使用相同的接口类型

2.Naming.lookup()寻址的格式【rmi://服务器地址/注册的远程方法名】,返回一个stub对象

3.客户端本地一定要有服务端rmic产生的stub类,否则RMI registry返回的stub对象不会被解序列化

RMI的注意事项

1.在启动远程服务前(java 实现服务的类),必须先启动rmiregistry

2.参数和返回类型必须是可序列化的

3.将stub类交给客户端

4.客户端和服务端一定要能够ping通,否则不能调用

 

遇到的问题

问题:

客户端启动时提示地址非法:java.net.MalformedURLException: invalid URL String: rmi://127.0.0.1:2000/Remote Hello

解决方法:

将远程的服务地址转换一下编码格式

String url="rmi://127.0.0.1:2000/Remote Hello";
url= URLEncoder.encode(url, "UTF-8");

MyRemote service=(MyRemote) Naming.lookup(url);

 

 

时间: 2024-10-12 12:59:41

java基础十一[远程部署的RMI](阅读Head First Java记录)的相关文章

java基础四 [构造器和垃圾回收](阅读Head First Java记录)

本章讲解了对象的创建到被回收的过程,讲述了对象的生命周期 堆(heap)与栈(stack) 实例变量:实例变量是只声明在类下,方法外的变量(实例变量默认值为0/0.0/false,引用的默认值为null) 局部变量:声明在方法中的变量,或方法中的参数.又被成为栈变量 例如: public class test{ int size; public void foof(int a){ int b; barf() } public void barf(){ Duck d =new Duck(24);

Java基础十一--多态

Java基础十一--多态 一.多态定义 简单说:就是一个对象对应着不同类型. 多态在代码中的体现: 父类或者接口的引用指向其子类的对象. 1 /* 2 3 对象的多态性. 4 5 class 动物 6 {} 7 8 class 猫 extends 动物 9 {} 10 11 class 狗 extends 动物 12 {} 13 14 15 16 猫 x = new 猫(); 17 18 动物 x = new 猫();//一个对象,两种形态. 19 20 21 22 猫这类事物即具备者猫的形态,

Java基础(十一) Stream I/O and Files

Java基础(十一) Stream I/O and Files 1. 流的概念 程序的主要任务是操纵数据.在Java中,把一组有序的数据序列称为流.根据操作的方向,可以把流分为输入流和输出流两种.程序从输入流读取数据,向输出流写出数据. 文件 输入流 输出流 文件 内存 -------------> Java程序 ------------------> 内存 键盘 控制台 | | 数据源 数据目的地 Java I/O系统负责处理程序的输入和输出,I/O类库位于java.io包中,它对各种常见的

java基础十[包、Jar存档文件和部署](阅读Head First Java记录)

将Java的class文件生成为可执行的Java应用程序.Java应用程序有三种:完全在本机执行的Jar(例如本机的GUI可执行程序):完全在服务器端远程执行的(例如浏览器来进行存取):介于两者之间的组合(例如客户端在本地,与远程服务器交互) 将class文件生成JAR   指定编译时class类文件的存储目录 打JAR(JavaArchiveFile)包仅需要编译后的class类文件,不需要源代码.java文件.可以通过-d指定编译结果输出的class存放目录 例如:java -d ../cl

JAVA 基础 / 第四课:在ECLIPSE中运行第一个 JAVA 程序以及找不到类的问题

2018-03-06 在Eclipse中运行java 程序 步骤 1 : 打开java文件 直接打开在 命令行Hello World 中创建的java 文件:HelloWorld.java 步骤 2 : 运行 点击绿色运行按钮,直接运行 在eclipse中,编译过程自动执行了 步骤 3 : 观察运行结果 一旦运行成功,会在下方出现控制台console界面 如果找不到控制台console窗口,使用如下步骤打开控制台窗口 步骤 4 : 打开控制台窗口 在默认情况下,console窗口是打开的,倘若无

java基础三 [深入多态,接口和多态](阅读Head First Java记录)

抽象类和抽象方法 1.抽象类的声明方法,在前面加上抽象类的关键词abstract abstract class canine extends animal{ public void roam(){} } 抽象类除了被继承过之外,是没有用途,没有值,没有目的.类中的方法可以当做子类的合约内容,合约是对其他程序的承诺协议 抽象类中可以带有抽象和非抽象的方法 如果类中有抽象方法,则类必定标识为抽象的. 2.抽象的方法没有实体 (因为方法中的程序代码没有意义.抽象类需要被extend过有意义,抽象方法一

java基础五 [数字与静态](阅读Head First Java记录)

本章主要讲了静态变量.静态方法,final关键词.以及介绍了怎么对数字和日期进行格式化输出.这里对这些内容进行了整理.本章还介绍了java.util.Date和java.util.Calendar来操作日期,但是这个直接看API就比较清楚,这里就不写了. static static标记过的,与类的实例对象无关 静态方法: 使用static关键词来标记静态方法.有些方法不需要用到类的实例变量,静态变量的代表“一种不依靠实例变量也就不需要对象的行为”.Math就是一个静态方法 调用静态方法:类名.方

java基础九[网络与线程](阅读Head First Java记录)

网络socket连接 Java API的网络功能包(java.net)已经将底层的TCP连接等都封装好了,我们只需要通过Socket对象来建立客户端和服务器的连接,然后客户端能向服务器发送请求,并接收服务端发来的数据即可 服务端和客户端大概的交互如下所示: 编写客户端程序 第一步:建立socket连接 需要客户端和服务器端都建立以下连接 Socket chatSocket=new Socket(“对方IP地址”,TCP端口号); IP类似门牌号,做寻址,找到服务器.端口号是找到这台服务器上的某个

java基础七 [图形用户接口](阅读Head First Java记录)

到目前为止我们接触的都是Java的命令行,但是为了让用户使用,必须有图形化界面,所以这章主要讲的是怎么使用GUI(图形用户接口) 创建一个GUI:javax.swing.* 本章讲的布局相关内容都是javax.swing包下的内容,常用的组件有JFrame,JButton,JRadioButton,JCheckBox,JLabel,JList,JScrollPane,JSlider,JTextArea,JTextField,JTable等 创建GUI第一步:创建window(JFrame) JF