发表于: 2020-06-13 23:53:10
1 1785
今天完成的事情:
MI:远程方法调用(Remote Method Invocation)。能够让在某个Java虚拟机上的对象像调用本地对象一样调用另一个java 虚拟机中的对象上的方法。并且屏蔽其中关于远程通信的内容
RMI远程调用步骤:
1,客户对象调用客户端辅助对象上的方法
2,客户端辅助对象打包调用信息(变量,方法名),通过网络发送给服务端辅助对象
3,服务端辅助对象将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象
4,调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象
5,服务端辅助对象将结果打包,发送给客户端辅助对象
6,客户端辅助对象将返回值解包,返回给客户对象
7,客户对象获得返回值
RMI的代码实现:
实现RMI所需的API几乎都在:
java.rmi:提供客户端需要的类、接口和异常;
java.rmi.server:提供服务端需要的类、接口和异常;
java.rmi.registry:提供注册表的创建以及查找和命名远程对象的类、接口和异常;
基本步骤
(1)创建远程接口,继承java.rmi.Remote接口;
(2)创建远程类,实现远程接口;
(3)创建服务器程序,在rmiregistry注册表中注册远程对象;
(4)创建客户端程序,负责定位远程对象,并且调用远程方法。
Java rmi
package com.ptteng.dao;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,
* 供客户端访问并提供一定的服务。JavaDoc描述:Remote 接口用于标识其方法可以从非本地虚拟机上
* 调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”
* (扩展 java.rmi.Remote 的接口)中指定的这些方法才可被远程调用。
*/
public interface IHello extends Remote {
/**extends了Remote接口的类或者其他接口中的方法若是声明抛出了RemoteException异常,
* 则表明该方法可被客户端远程访问调用。
*/
public String sayHelloToSomeBody(String someBodyName) throws RemoteException;
}
实现类
package com.ptteng.dao.Impl;
import com.ptteng.dao.IHello;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
// 这个实现必须有一个显式的构造函数,并且要抛出一个RemoteException异常
/*
* 远程对象必须实现java.rmi.server.UniCastRemoteObject类,这样才能保证客户端访问获得远程对象时,
* 该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,
* 而服务器端本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,用于与服务器端的通信,
* 而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。
*/
// java.rmi.server.UnicastRemoteObject构造函数中将生成stub和skeleton
public class HelloImpl extends UnicastRemoteObject implements IHello {
// 这个实现必须有一个显式的构造函数,并且要抛出一个RemoteException异常
public HelloImpl () throws RemoteException {
super();
}
@Override
public String sayHelloToSomeBody(String someBodyName) throws RemoteException {
System.out.println("你好啊");
return someBodyName+"这是传入的参数";
}
}
服务层
package com.ptteng.Server;
import com.ptteng.dao.IHello;
import com.ptteng.dao.Impl.HelloImpl;
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
/**注册远程对象,向客户端提供远程对象服务
* 远程对象是在远程服务上创建的,你无法确切地知道远程服务器上的对象的名称
* 但是,将远程对象注册到RMI Service之后,客户端就可以通过RMI Service请求
* 到该远程服务对象的stub了,利用stub代理就可以访问远程服务对象了
*/
public class HelloServer {
public static void main(String args[]) {
try {
/* 生成stub和skeleton,并返回stub代理引用 */
IHello hello = new HelloImpl();
//加上此程序,就可以不要在控制台上开启RMI的注册程序,1099是RMI服务监视的默认端口
LocateRegistry.createRegistry(8888);
// 如果配置在远程服务器,把地址换成你的ip
System.setProperty("java.rmi.server.hostname","127.0.0.1");
Naming.bind("rmi://localhost:8888/Hello", hello);
System.out.println(">>>>>INFO:远程IHello对象绑定成功!");
} catch (RemoteException e) {
System.out.println("创建远程对象发生异常!");
e.printStackTrace();
} catch (AlreadyBoundException e) {
System.out.println("发生重复绑定对象异常!");
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println("发生URL畸形异常!");
e.printStackTrace();
}
}
}
客户端
public class Client {
public static void main(String args[]) {
try {
// 填写服务器ip
IHello hello = (IHello) Naming.lookup("rmi://127.0.0.1:8888/Hello");
System.out.println(hello.sayHelloToSomeBody("大王大王"));
} catch (NotBoundException e) {
} catch (MalformedURLException e) {
e.printStackTrace();
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
里面的东西都是java自带的
开启服务段
客户端
评论