标签:
一、动机 需求
现在有这样一个需求:有一个出版社,该出版社有一个工厂,专门用来生产制造图书,该工厂里有很多台生产制造图书的机器。每个机器有自己的位置坐标,用 int表示,机器的状态,{正在工作,暂停,故障},已经印刷了多少页图书。在出版社 在工厂 厂长的电脑屏幕上,可以随时打印出任何一台机器的报告信息(report infomation)。
下来 我们用代码实现这个需求:
PrinterMachine.java
package com.crg;
public class PrinterMachine {
//打印机位置,及第几台打印机
private int location;
//打印机当前的打印页数
private int pages;
//打印机当前的状态
private int state;
public PrinterMachine(int location, int state, int pages){
this.pages = pages;
this.location = location;
this.state = state;
}
public int getLocation(){
return location;
}
public int getPages(){
return pages;
}
public int getState(){
return state;
}
}
打印机类,可以获得该打印机的位置信息,当前页数,当前状态;
---------------------------------------------
PrinterMonitor.java
package com.crg;
import com.crg.PrinterMachine;
public class PrinterMonitor{
private PrinterMachine printerMachine;
public PrinterMonitor(PrinterMachine printerMachine ){
this.printerMachine = printerMachine;
}
public void report(){
System.out.println("the PrinterMachine location is :" + printerMachine.getLocation());
System.out.println("the PrinterMachine state is :" + printerMachine.getState());
System.out.println("the PrinterMachine pages is :" + printerMachine.getPages());
}
}
打印机监控类,可以打印出 那个位置的打印机的当前信息,并生成报告
---------------------------------------------
PrinterMonitorTest.java
package com.crg;
import com.crg.PrinterMachine;
import com.crg.PrinterMonitor;
public class PrinterMonitorTest{
public static void main(String args[]){
if(args.length < 3){
System.out.println("the args must be three or more");
System.exit(1);
}
int location = Integer.parseInt(args[0]);
int state = Integer.parseInt(args[1]);
int pages = Integer.parseInt(args[2]);
PrinterMachine printerMachine = new PrinterMachine(location, state, pages);
PrinterMonitor printerMonitor = new PrinterMonitor(printerMachine);
printerMonitor.report();
}
}
---------------------------------------------
测试类,从命令行窗口,接受三个参数,分别为 打印机位置,打印机当前状态,当前打印页数
运行效果如下:
crg@crg-pc:~/my_learning/code/proxypattern$ javac com/crg/PrinterMonitorTest.java
crg@crg-pc:~/my_learning/code/proxypattern$ java com/crg/PrinterMonitorTest 12 1 1126
the PrinterMachine location is :12
the PrinterMachine state is :1
the PrinterMachine pages is :1126
二、新的需求
一中的实现是在,同一台电脑,同一个JVM 上运行的,现在 又有一个新的需求,打印机PrinterMachine.java 运行在工厂的 JVM 上,而厂长要在 自己的办公室里,查看打印机监察器(PrinterMonitor.java)的 打印报告,即 打印机监察器运行在,厂长办公室的JVM上。但是呢,要想获得,打印机的详细信息报告,就必须把 PrinterMachine.java 对象传给 PrinterMonitor.java,打印机监察器才能生成报告。
解决办法如下:
不需要修改之前的代码,把远程PrinterMachine.java 在本地的代理对象 交给打印机监察器,把这个打印机在本地的代理对象(proxy),当做真正的 PrinterMachine.java 对象,其实一切的动作,是,代理对象利用网络和真正的打印机对象沟通.
三、利用java 内置 JAVA RMI 实现远程访问
1、制作远程接口
package com.crg;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface MyRemote extends Remote {
public String sayHello() throws RemoteException;
}
2、制作远程服务实现
package com.crg;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
/**
*
*/
private static final long serialVersionUID = 1L;
protected MyRemoteImpl() throws RemoteException {
super();
}
@Override
public String sayHello() throws RemoteException {
return "Server says ‘Hey‘";
}
public static void amin(String[] args) {
try {
MyRemote service = new MyRemoteImpl();
Naming.rebind("RemoteHello", service);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、产生 Stub(客户辅助对象,也就是远程服务对象的代理),Skeleton(服务辅助对象)
使用如下命令即可:
-rw-rw-r-- 1 crg crg 600 7月 17 17:25 MyRemoteImpl.java
-rw-rw-r-- 1 crg crg 153 7月 17 17:25 MyRemote.java
crg@crg-pc:~/my_learning/code/com/crg$ javac MyRemoteImpl.java
crg@crg-pc:~/my_learning/code/com/crg$ rmic -keep -v1.1 MyRemoteImpl
crg@crg-pc:~/my_learning/code/com/crg$ ll
total 40
drwxrwxr-x 2 crg crg 4096 7月 17 17:31 ./
drwxrwxr-x 3 crg crg 4096 7月 17 16:16 ../
-rw-rw-r-- 1 crg crg 215 7月 17 17:31 MyRemote.class
-rw-rw-r-- 1 crg crg 771 7月 17 17:31 MyRemoteImpl.class
-rw-rw-r-- 1 crg crg 600 7月 17 17:25 MyRemoteImpl.java
-rw-rw-r-- 1 crg crg 1362 7月 17 17:31 MyRemoteImpl_Skel.class
-rw-rw-r-- 1 crg crg 1260 7月 17 17:31 MyRemoteImpl_Skel.java
-rw-rw-r-- 1 crg crg 1604 7月 17 17:31 MyRemoteImpl_Stub.class
-rw-rw-r-- 1 crg crg 1566 7月 17 17:31 MyRemoteImpl_Stub.java
-rw-rw-r-- 1 crg crg 153 7月 17 17:25 MyRemote.java
4、实现客户端
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class MyRemoteClient {
public static void main(String[] args) {
new MyRemoteClient().go();
}
public void go(){
MyRemote service = null;
try {
service = (MyRemote) Naming.lookup("rmi://10.0.0.54/RemoteHello");
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (RemoteException e1) {
e1.printStackTrace();
} catch (NotBoundException e1) {
e1.printStackTrace();
}
String result = null;
try {
result = service.sayHello();
} catch (RemoteException e) {
e.printStackTrace();
}
System.out.println("the result is: " + result);
}
}
5、开启一个终端 执行 rmiregistry
6、启动远程服务
crg@crg-pc:~/my_learning/code/com/crg$ java MyRemoteImpl
7、启动客户端
结果如下:
crg@crg-pc:~/Desktop/client$ java MyRemoteClient
the result is: Server says ‘Hey‘
crg@crg-pc:~/Desktop/client$
已经成功实现了 客户端远程调用 服务器端的 方法了
贴出rmic 自动生成的 MyRemoteImpl_Stub.java 和 MyRemoteImpl_Skel.java 的代码
// Stub class generated by rmic, do not edit.
// Contents subject to change without notice.
public final class MyRemoteImpl_Stub
extends java.rmi.server.RemoteStub
implements MyRemote, java.rmi.Remote
{
private static final java.rmi.server.Operation[] operations = {
new java.rmi.server.Operation("java.lang.String sayHello()")
};
private static final long interfaceHash = 6486744599627128933L;
// constructors
public MyRemoteImpl_Stub() {
super();
}
public MyRemoteImpl_Stub(java.rmi.server.RemoteRef ref) {
super(ref);
}
// methods from remote interfaces
// implementation of sayHello()
public java.lang.String sayHello()
throws java.rmi.RemoteException
{
try {
java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash);
ref.invoke(call);
java.lang.String $result;
try {
java.io.ObjectInput in = call.getInputStream();
$result = (java.lang.String) in.readObject();
} catch (java.io.IOException e) {
throw new java.rmi.UnmarshalException("error unmarshalling return", e);
} catch (java.lang.ClassNotFoundException e) {
throw new java.rmi.UnmarshalException("error unmarshalling return", e);
} finally {
ref.done(call);
}
return $result;
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.rmi.RemoteException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
}
// Skeleton class generated by rmic, do not edit.
// Contents subject to change without notice.
public final class MyRemoteImpl_Skel
implements java.rmi.server.Skeleton
{
private static final java.rmi.server.Operation[] operations = {
new java.rmi.server.Operation("java.lang.String sayHello()")
};
private static final long interfaceHash = 6486744599627128933L;
public java.rmi.server.Operation[] getOperations() {
return (java.rmi.server.Operation[]) operations.clone();
}
public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash)
throws java.lang.Exception
{
if (hash != interfaceHash)
throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch");
MyRemoteImpl server = (MyRemoteImpl) obj;
switch (opnum) {
case 0: // sayHello()
{
call.releaseInputStream();
java.lang.String $result = server.sayHello();
try {
java.io.ObjectOutput out = call.getResultStream(true);
out.writeObject($result);
} catch (java.io.IOException e) {
throw new java.rmi.MarshalException("error marshalling return", e);
}
break;
}
default:
throw new java.rmi.UnmarshalException("invalid method number");
}
}
}
四、用远程代理 来改写开始那个图书工厂的例子;
先看一个逻辑思路图:
标签:
原文地址:http://blog.csdn.net/jack_sivenchen/article/details/51932375