RemoteProxy
远程代理模式是代理模式的一个具体应用案例,当你需要在本地的JVM上调用其他JVM上对象的方法时, 远程代理可以非常容易的帮你实现。
1.创建远程接口
package
com.dreamli.rmi.test01;
import
java.rmi.Remote;
import
java.rmi.RemoteException;
/**
*
@Description
: 定义远程接口,需要扩展 Remote并在远程方法上抛出 RemoteException
*
@Warning
:
*
@Author
DreamLi
*
@Package
ProxyPattern
-
com.dreamli.rmi.test01
-
MyRemote.java
*
@Date
: 2018年1月21日 下午12:54:03
*
@Version
: 1.0.0
*/
public
interface
MyRemote
extends
Remote {
public
String sayHello()
throws
RemoteException;
}
2.实现远程接口,提供真正的远程服务
package
com.dreamli.rmi.test01;
import
java.rmi.Naming;
import
java.rmi.RemoteException;
import
java.rmi.server.UnicastRemoteObject;
/**
*
@Description
: 远程服务
---
提供真实服务的对象
*
@Warning
:
*
@Author
DreamLi
*
@Package
ProxyPattern
-
com.dreamli.rmi.test01
-
MyRemoteImpl.java
*
@Date
: 2018年1月21日 下午1:06:04
*
@Version
: 1.0.0
*/
public
class
MyRemoteImpl
extends
UnicastRemoteObject
implements
MyRemote {
private
static
final
long
serialVersionUID
= 6780156706603775814L;
protected
MyRemoteImpl()
throws
RemoteException {
super
();
}
@Override
public
String sayHello()
throws
RemoteException {
return
"Hello, RMI..."
;//真实的服务
}
public
static
void
main(String[]
args
) {
try
{
// 创建远程服务对象
MyRemote
myRemote
=
new
MyRemoteImpl();
// 绑定远程服务对象到
rmiregistry
Naming.rebind(
"RemoteServer"
,
myRemote
);
}
catch
(Exception
e
) {
e
.printStackTrace();
}
}
}
3.产生Stub和Skeleton
将目录切到项目的bin目录下或WEB项目的classes目录下, 运行 rmic com.dreamli.rmi.test01.MyRemoteImpl 产生stub文件
4.启动registry
依然是在bin/classes 目录下运行 remiregistry 命令启动registry
5.启动服务
运行远程服务实现的 main() 方法 —> MyRemoteImpl
6.测试
package
com.dreamli.rmi.test01;
import
java.rmi.Naming;
public
class
MyRemoteClient {
public
static
void
main(String[]
args
) {
new
MyRemoteClient().go();
}
public
void
go() {
try
{
MyRemote
myRemote
= (MyRemote) Naming.lookup(
"rmi://127.0.0.1/RemoteServer”
);// RemoteServer 就是注册(rebind)时的 key
String
hello
=
myRemote
.sayHello();
System.
out
.println(
hello
);
}
catch
(Exception
e
) {
e
.printStackTrace();
}
}
}
运行 client,结果如下:
虽然这种方式可以实现, 但是正如上面图中所示, rmic 方式已经过时,因此使用 Registry 代替
2.Registry实现RMI
远程接口依然不变
package com.dreamli.rmi.test02;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* @Description: 定义远程接口,需要扩展 Remote并在远程方法上抛出 RemoteException
* @Warning:
* @Author DreamLi
* @Package ProxyPattern - com.dreamli.rmi.test01 - MyRemote.java
* @Date: 2018年1月21日 下午12:54:03
* @Version: 1.0.0
*/
public interface MyRemote extends Remote {
public String sayHello() throws RemoteException;
}
远程服务
package com.dreamli.rmi.test02;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* @Description: 远程服务 --- 提供真实服务的对象
* @Warning:
* @Author DreamLi
* @Package ProxyPattern - com.dreamli.rmi.test01 - MyRemoteImpl.java
* @Date: 2018年1月21日 下午1:06:04
* @Version: 1.0.0
*/
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
private static final long serialVersionUID = 6780156706603775814L;
protected MyRemoteImpl() throws RemoteException {
super();
}
@Override
public String sayHello() throws RemoteException {
return "Hello, RMI...";
}
public static void main(String[] args) {
try {
// 创建远程服务对象
MyRemote myRemote = new MyRemoteImpl();
// 绑定远程服务对象到 rmiregistry
Naming.rebind("RemoteServer", myRemote);
} catch (Exception e) {
e.printStackTrace();
}
}
}
用来代替 rmic 和 registry 的registry
package com.dreamli.rmi.test02;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class ServerRegistry {
private static Registry registry;
private static Registry getRegistry() throws RemoteException {
try {
return registry == null ? (registry = LocateRegistry.createRegistry(9001)) : registry;
} catch (RemoteException e) {
e.printStackTrace();
}
throw new RemoteException("Create registry faild...");
}
public static void main(String[] args) {
try {
MyRemote server = new MyRemoteImpl();
getRegistry().bind("RemoteServer", server);
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端:
package com.dreamli.rmi.test02;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class MyRemoteClient {
public static void main(String[] args) {
new MyRemoteClient().go();
}
public void go() {
try {
// MyRemote myRemote = (MyRemote) Naming.lookup("rmi://127.0.0.1:9001/RemoteServer”);//这种方式也可以
Registry registry = LocateRegistry.getRegistry("127.0.0.1", 9001);
MyRemote myRemote = (MyRemote) registry.lookup("RemoteServer");
String hello = myRemote.sayHello();
System.out.println(hello);
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试:
首先运行 ServerRegistry, 然后运行 MyRemoteClient, 可以看到远程服务的返回数据: