headFirst学习笔记之十一:代理模式(5.2)

1.目前任务:

上一章的万能糖果机的CEO,希望我们能发给它一份库存以及机器状态的报告。(简直就是小cese,CEO一定会被我的编码能力折服的hiahiahia~)

(1)在上一章的代码中加入location变量(2)然后添加糖果机监视器这个类。有一个问题:我点击运行后控制台什么反应都没有,我也不能输入信息。这是什么情况?

 1 public class GumballMachine {
 2     String location;
 3     int count = 0;
 4     public GumballMachine(String location, int count) {
 5     super();
 6     //其他代码
 7     this.location = location;
 8     }
 9
10     public String getLocation() {
11     return location;
12     }
13
14     //其他方法
15 }
 1 import unit10.state.GumballMachine;
 2
 3 public class GumballMonitor {
 4     GumballMachine machine;
 5
 6     public GumballMonitor(GumballMachine machine) {
 7         super();
 8         this.machine = machine;
 9     }
10
11     public void report(){
12         System.out.println("gumball machine: "+machine.getLocation());
13         System.out.println("current inventory: "+machine.getCount());
14         System.out.println("current state: "+machine.getState());
15     }
16 }
 1 import unit10.state.GumballMachine;
 2
 3 public class GumballMachineTestDrive {
 4     public void main(String[] args){
 5         int count = 0;
 6         //利用命令行来传入位置和数目
 7         if(args.length<2){
 8             System.out.println("GumballMachine <name><inventory>");
 9             System.exit(1);
10         }
11
12         count = Integer.parseInt(args[1]);
13         GumballMachine machine = new GumballMachine(args[0],count);
14         GumballMonitor monitor = new GumballMonitor(machine);
15
16         monitor.report();
17         //其他测试代码
18     }
19 }

但是问题来了:CEO想要的是远程监控糖果机,而现在监视器和糖果机在同一个JVM上运行!

解决办法:远程代理。远程代理就好比是“远程对象的本地代表”。远程对象:活在不同java虚拟机(jvm)堆中。本地代表:可以由本地方法调用的对象,其行为会转发到远程对象中。这里的“本地堆”就是ceo的桌面,它其实是和代理在聊天,它以为他在和真正的糖果机聊天。"远程堆"就是糖果机,它才是真正做事的。

(1)了解RMI

(2)把gumballMachine变成远程服务,提供一些可被远程调用的方法。

(3)创建一个能和远程gumballMachine沟通的代理proxy(这里需要用到RMI),然后和监视系统GumballMonitor结合。

2.RMI

JAVA已经内置远程调用的功能了,我们只需要修改下代码,使其符合RMI的要求即可。

客户对象---客户辅助对象(stub)---服务辅助对象(skeleton)--服务对象

(1)将一个普通对象变成可以被远程客户调用的服务:

a.制作远程接口:客户辅助对象(stub)和服务对象实现此接口。

b.制作远程的实现:真正的行为实现。

c.利用rmic产生的stub和skeleton:这就是客户和服务的辅助类,当我们运行rmic工具时,这都会自动处理。

d.启动RMI registry:就像一个电话簿,所有注册的服务都在这里。

e.开启远程服务:注册服务,开始运行。

1 import java.rmi.Remote;
2 import java.rmi.RemoteException;
3
4 public interface MyRemote extends Remote {
5     //因为远程方法调用会用到网络和I/O,所以必须考虑成有风险的
6     //方法的返回类型必须是primitive类型或者serializable类型,因为需要通过网络运送
7     public String sayHello() throws RemoteException;
8 }
 1 import java.rmi.Naming;
 2 import java.rmi.RemoteException;
 3 import java.rmi.server.UnicastRemoteObject;
 4
 5 public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
 6
 7     protected MyRemoteImpl() throws RemoteException {
 8         super();
 9     }
10
11     public String sayHello(){
12         return "server says: hey";
13     }
14
15     public static void main(String[] args){
16         try {
17             //新建一个远程对象
18             MyRemote service = new MyRemoteImpl();
19             //将远程对象绑定到RMI regstry(类似电话簿的东西)中,注册名为RemoteHello,
20             //用户client就通过这个名字去找对应的代理:“我要找名字叫做RemoteHello”的stub
21             Naming.rebind("RemoteHello", service);
22         } catch (Exception e) {
23             e.printStackTrace();
24         }
25     }
26 }

我的环境变量是对的,所以还是不知道是什么原因。

已解决:书上的命令是%rmic,但是我要打rmic才是对的,%不需要,那只是它的输入提示符,不是命令部分的东西。

(2)获取sub对象:当服务为绑定到RMI registry中时,其实真正被绑定的是stub,所以可以通过lookup找出来。

 1 import java.rmi.*;
 2
 3 public class MyRemoteClient {
 4     public static void main(String[] args){
 5         new MyRemoteClient().go();
 6     }
 7
 8     public void go() {
 9         try {
10             MyRemote service = (MyRemote) Naming.lookup("rmi://10.15.199.179/RemoteHello");
11             String s = service.sayHello();
12             System.out.println(s);
13         } catch (Exception e) {
14             e.printStackTrace();
15         }
16     }
17 }

3.让gumballMachine成为远程服务:

(1)为gumballMachine创建远程接口。

(2)确认接口方法的所有返回类型都是可序列化的:在这里state接口不是可序列化的,所以要extends Serializable。但是没完呢!上一章程序中,我们

(3)在gumballMachine中实现此接口。

1 import java.rmi.*;
2 import unit10.state.State;
3
4 public interface GumballMachineRemote extends Remote {
5     public int getCount() throws RemoteException;
6     public String getLocation() throws RemoteException;
7     public State getState() throws RemoteException;
8 }
1 import java.io.Serializable;
2
3 public interface State extends Serializable{
4     ...
5 }
时间: 2024-11-08 02:15:06

headFirst学习笔记之十一:代理模式(5.2)的相关文章

Java学习笔记——设计模式之四.代理模式

To be, or not to be: that is the question. --<哈姆雷特> 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 上代码: 1 package cn.no4.proxy; 2 3 public interface IMakeMoney { 4 5 void makeMoney(); 6 } 1 package cn.no4.proxy; 2 3 public class Proxy implements IMakeMoney { 4

java学习笔记-设计模式9(代理模式)

意图 为其他对象提供一种代理以控制对这个对象的访问. public interface Sourceable { public void method(); } public class Source implements Sourceable{ @Override public void method() { System.out.println("this is original method!"); } } public class Proxy implements Source

headFirst学习笔记之十一:代理模式之三保护代理(5.2)

1.动态代理:java在java.lang.reflect包中有自己的代理支持,利用这个包你可以在运行时动态的创建一个代理类,实现一个或者多个接口,并且将方法的调用转发到你指定的类. 保护代理:根据访问权限决定客户可否访问对象的代理. 2.任务:对象村的小伙伴们要相亲啦~请负责帮忙实现约会服务系统. (1)PersonBean接口,允许设置或获取一个人的信息等. 1 public interface PersonBean { 2 public String getName() ; 3 publi

headFirst学习笔记之六:命令模式(4.30)

1.要完成的任务: 目标:设计一个家电自动化遥控器的API,让每个插槽都能控制一个或者一组装置.能够控制目前的装置和任何未来可能出现的装置这一点非常重要. 已知条件: (1)这个遥控器有7个可编程的插槽(每个都可以指定到一个不同的家电装置),每个插槽都有对应的开关按钮.这个遥控器还具备一个整体的撤销按钮. (2)提供一个光盘,里面是厂商类,用来控制家电自动化装置,比如电灯.风扇.热水器等可控制装置.部分如下所示,类不少,接口也各有差异. 1 class TV{ 2 on(){} 3 off(){

马哥学习笔记二十一——LVS DR模型

kernel parameter: arp_ignore: 定义接收到ARP请求时的响应级别: 0:只要本地配置的有相应地址,就给予响应: 1:仅在请求的目标地址配置请求到达的接口上的时候,才给予响应: arp_announce:定义将自己地址向外通告时的通告级别: 0:将本地任何接口上的任何地址向外通告: 1:试图仅向目标网络通告与其网络匹配的地址: 2:仅向与本地接口上地址匹配的网络进行通告: curl命令选项: --cacert <file> CA证书 (SSL) --capath &l

《Javascript权威指南》学习笔记之十一:处理字符串---String类和正则表达式

一.正则表达式的基本语法 1.概念:正则表达式由普通字符和特殊字符(元字符)组成的文本模式,该模式描述在查找字符串主体时待匹配的一个或者多个字符串.正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配. 普通字符包括所有的大小写字母字符.所有数字.所有标点符号及一些特殊符号.普通字符本身可以组成一个正则表达式,也可以和元字符组合组成一个正则表达式:而元字符则具有特殊的含义,包括().[].{}./.^.$.*.+.?...|.-.?:.?=.?! 2.基本语法 3.优先权含义 二.使用

VSTO 学习笔记(十一)开发Excel 2010 64位自定义公式

原文:VSTO 学习笔记(十一)开发Excel 2010 64位自定义公式 Excel包含很多公式,如数学.日期.文本.逻辑等公式,非常方便,可以灵活快捷的对数据进行处理,达到我们想要的效果.Excel的内置公式虽然强大,但是在ERP等系统中,往往需要进行很多业务上的计算,如收发存台账.指定年.月.部门的消耗查询等,都是需要从数据库中查询的,且和业务紧密相连.这时仅仅依靠Excel的内置公式就不够了,需要添加自定义的公式来进行这些业务计算. 测试代码下载 本系列所有测试代码均在Visual St

angular学习笔记(三十一)-$location(2)

之前已经介绍了$location服务的基本用法:angular学习笔记(三十一)-$location(1). 这篇是上一篇的进阶,介绍$location的配置,兼容各版本浏览器,等. *注意,这里介绍的是基于angular-1.3.2版本的,低版本的$location可能会有问题. hashbang模式和history api创建单页应用 首先,$location是用在单页应用里的...(废话,angular就是用在单页的)...所以,$location处理的是url改变,但是不刷新页面的情况.

【Unity 3D】学习笔记三十一:游戏元素——地形元素

地形元素 一般情况下,为了使游戏更具有美观性,会在游戏地形上放置很多的元素,这些元素是与地形分开的.主要包括:树木,草地,自定义网格模型. 树元素 首先导入系统提供的树木标准资源包,在project视图中,点击鼠标右键,然后从菜单中选择import-----tree creator.接着在地形菜单里点击第五个按钮,添加树模型.然后点击edit trees按钮,将弹出如下列表: add tree:添加一个树模型 edit tree:编辑一个树模型 remove tree:删除树模型 点击add t