假设现在需要设置一个监视器Monitor,能够监视糖贩卖机GumballMachine的状态,位置信息、还有多少糖果等。一个简单的想法就是创建一个Monitor的类,构造参数包括GumballMachine。然后就可以调用GumballMachine的一些状态函数。
但是如果GumballMachine在另一台机器上、或者在不同的Java堆上,显然是不能够将GumballMachine的引用传递过来。
这是后就需要使用代理模式来解决。
思路:添加一个新的类叫做MonitorProxy。Monitor和MonitorProxy在一个Java堆上,MonitorProxy这个代理负责与远程的GumballMachine进行沟通,得到数据后把自己伪装成GumballMachine来被MonitorProxy调用。
我们要这设计这样一个系统:该系统允许我们调用本地的一个对象,本地的这个对象又能够将请求转发到远程对象上。
四个关键的角色 client 、client helper、service helper、Service
client helper的作用是让client调用和调用远程remoter效果一样。client helper处理转发了client的请求。
换句话说,从client的角度来看,client就是在调用一个远程的服务。client helper假装自己是service
client helper有和service一样的方法。但是他们的逻辑不同,client helper里面的方法是对service进行响应请求、然后进行参数转换返回给client的。
同客户端一样,存在一个Service helper负责处理对话(可能是Socket)
Java RMI已经封装好了相关功能。不需要自己动手写网络和I/O相关的代码了。和调用本地的对象一样。唯一的区别时会有网络通讯,可能引起失败抛出异常。
client helper 叫做RMI Stub
service helper 叫做RMI Skeleton
一共五步走:
这个远程接口所定义的方法是client远程调用的。这也就意味着stub和实际的service都要实现这个接口
//1. 扩展java.rmi.Remote接口
public interface MyRemote extends Remote{
//2. 接口中所有的函数都要能够抛出RemoteException异常
//因为涉及到网络或者I/O,可能出现连接错误等。
public String sayHello() throws RemoteException;
//3. 要保证参数和返回值都是基本的数据类型或者是可序列化的。
}
远程的class要实现上一步定义的接口
// 1. 注意MyRemoteImpl所继承的类UnicastRemoteObject, 这个类定义了一些远程服务所需要的功能函数。
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{
// 2. 抛出这个异常的原因是它的父类可能UnicastRemoteObject会抛出这个异常,所以子类也一样。
public MyRemoteImpl() throws RemoteException{
}
public String sayHello() {
return "server says, hi";
// other impl
}
// 主函数入口。方便起见直接写在了这个类
public static void main (String[] args) {
/*方法一*/
// 需要运行第四步命令
try {
MyRemote service = new MyRemoteImpl();
Naming.rebind(“RemoteHello”, service); //在RMI中注册
} catch(Exception ex) {
ex.printStackTrace();
}
}
/*方法二*/
//使用内在注册器,不用单独运行rmiregistry服务。
try {
//默认端口1099
Registry registry = LocateRegistry.createRegistry(1099);
MyRemoteImpl service = new MyRemoteImpl();
registry.bind("RemoteHello", service); // 在RMI中注册
System.out.println("Run Successfully");
} catch (Exception ex) {
ex.printStackTrace();
}
}
定义好service,需要使用。方法就是把上面的MyRemoteImpl实例化之后,在RMI 中注册这个服务。
try{
MyRemote service = new MyRemoteImpl();
Naming.rebind(“RemoteHello”, service); //起一个名字并且注册。
}catch(Exception ex){
…
}
使用rmic工具生成两个类:
rmic MyRemoteImpl
rmiregistry
确保运行的文件能够到达你的类。稳妥的办法是从你的类文件运行此命令。
例如从全限定类名的根目录开始。比如bin/test/MyRemoteImpl.class
那么从bin目录运行
java MyRemoteImpl
xxxx是main函数的远程服务。
从全限定类名的根目录开始。同上。
client如何能够得到stub object呢?
import java.rmi.*;
public class MyRemoteClient {
// 主程序入口
public static void main (String[] args) {
new MyRemoteClient().go();
}
public void go() {
try {
//查找,返回时Object,需要Cast
//如果是默认端口和本地地址,可以忽略不写
MyRemote service = (MyRemote) Naming.lookup(“rmi://127.0.0.1:1099/RemoteHello”);
String s = service.sayHello();
System.out.println(s);
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
为另一个对象提供一个代理或者占位符,来控制对他的访问。
几个控制访问的方法:
一个远程代理控制对远程对象的访问
虚拟代理控制对创建成本较高的资源的访问
保护代理控制对于权限资源的访问
上面提的那种
虚拟代理用来标识一个需要昂贵代价去创建的对象。虚拟代理通常来推迟这个对象的创建,直到这个对象被需要时再创建。在被代理对象创建完成之前,虚拟代理扮演者被代理者(RealSubject)的角色, 创建完成之后,虚拟代理把请求转交给被代理对象。
例如:播放在线音乐,当音乐封面没有被下载的时候,虚拟代理充当封面的角色(可以使一串字符串“正在下载封面”,或者其他的某个默认图片), 一旦封面下载完成,虚拟代理就把所有调用的方法委托给实际的图片。
// Head Fist Design Pattern P456
class ImageProxy implements Icon {
ImageIcon imageIcon;
URL imageURL;
Thread retrievalThread;
boolean retrieving = false;
public ImageProxy(URL url) {
imageURL = url; }
public int getIconWidth() {
if (imageIcon != null) {
return imageIcon.getIconWidth();
} else {
return 800;
}
}
public int getIconHeight() {
if (imageIcon != null) {
return imageIcon.getIconHeight();
} else {
return 600;
}
}
public void paintIcon(final Component c, Graphics g, int x, int y) {
if (imageIcon != null) {
imageIcon.paintIcon(c, g, x, y);
} else {
g.drawString(“Loading CD cover, please wait...”, x+300, y+190);
if (!retrieving) {
retrieving = true;
retrievalThread = new Thread(new Runnable() {
public void run() {
try {
imageIcon = new ImageIcon(imageURL, “CD Cover”);
c.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
});
retrievalThread.start();
}
}
}
}
文章浏览阅读2k次。目录shell函数1.函数的作用2.函数的基本格式3.函数注意事项4.函数调用的方法5.函数的返回值6.函数的传参7.在外部调用函数8.函数变量的作用范围9.函数的递归shell函数1.函数的作用语句块定义成函数约等于别名,定义函数,再引用函数封装的可重复利用的具有特定功能的代码2.函数的基本格式法一:[function] 函数名 (){ 命令序列 [return x] #使用return或者exit可以显式的结束函数} 法二:函数名(){ 命令序列}3._shell脚本函数调用怎么写
文章浏览阅读157次。概念适配器模式(Adapater Pattern)是指将一个类的接口转换成用户期望的另一个接口,使原本接口不兼容的类可以一起工作,属于结构型设计模式。场景场景一已经存在的类的方法和需求不匹配(方法结果相同或者相似)的情况场景二适配器模式不是软件设计初始阶段考虑的设计模式,是随着软件的发展,由于不同的产品、不同的厂家造成功能类似而接口不同的问题的解决方法,有点亡羊补牢的感觉。生活中电源..._软件设计模式实验7适配器模式
文章浏览阅读180次。点击欧盟IT那些事关注我们公告:因企鹅审核规定,本公众号从《德国IT那些事》更名为《欧盟IT那些事》。你们要的比赛来了。宣传防骗,人人有责,让骗子无人可骗。近期在德国各地华人群中,频繁..._选帅哥大赛开始
文章浏览阅读1.9k次,点赞5次,收藏6次。根据RFC 6455标准,Websocket协议提供了一种标准化的方式在客户端和服务端之间通过TCP连接建立全双工、双向通信渠道。它是一种不同于HTTP的TCP协议,但是被设计为在HTTP基础上运行。Websocket交互始于HTTP请求,该请求会通过HTTPUpgrade请求头去升级请求,进而切换到Websocket协议。我们可以看到在该请求报文中有两个特殊的请求头,一个是Upgrade请求头,代表升级为websocket协议。还有一个是Connection请求头,代表升级连接。_qwebsocket的唯一标识
文章浏览阅读3.5k次。将hive数据 查询出结果保存在hdfs set mapred.reduce.tasks = 1;set mapred.job.name=recommend_$idate;insert overwrite directory '/user/client/' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'select * from t..._经过hive计算后,写入到hdfs中的统计数据,想要展现给用户,最佳方式是什么
文章浏览阅读2.5k次。gitHop地址https://github.com/wechatpay-apiv3/wechatpay-apache-httpclientimport cn.hutool.json.JSONObject;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.node.ObjectNode;import com.vworld365.common.exception.Req_wechatpay-apache-httpclient 连接池
文章浏览阅读624次,点赞7次,收藏10次。原题题目(谷歌翻译)全检查点通过图闲谈说真的 第一次没有上CSDN先瞄一眼人家的思路 然后再上手做这道题自己完全独立做 竟然能够完全有思路尤其在对于Dijkstra算法这道题其实也就是变了一下形就是把每条边的权值当成了1然后再分别计算每个点的最短路径只是还要考虑另外几个点下面思路分析的时候 会专门讲的总而言之 真的当这道题做出来的时候我觉得喜悦的感觉已经少了很多了更多的感觉是理所应当这就是我应该做出来的题的感觉现在也许比较刚开始处理一道题 根本不知所云一道题可能_7-11 saving james bond - hard version (30 分)测试点3,4
文章浏览阅读406次。企业云原生之微服务全面解析_云服务 微服务
文章浏览阅读1.2w次,点赞3次,收藏19次。一、PHP开源源代码下载地址:https://github.com/php/php-src.git二、PHP的构成1、目录结构2、目录分析(1)sapi目录是PHP的应用接口层。(2)main为php的主要代码,主要是输入/输出、Web通信、PHP框架的初始化操作等,比如fastcgi协议的解析、扩展的加载、PHP配置的解析等工作都是在这里完成的。(3)Zen..._php返回数据结构中生命周期时间
文章浏览阅读1.8k次。本文主要展示如何用flask实现token验证及跨域问题,本文主要参考文章为:Flask实现token认证 - 简书但基于此,更详细的实现了包括解决频繁options问题、全局请求token验证问题。run.pyfrom flask import Flask, g, jsonify, redirect, request, make_responsefrom flask_httpauth import HTTPBasicAuthfrom itsdangerous import Ti.._flask options
文章浏览阅读2.8k次。服务端管理员调用的接口没有鉴权,且将内容直接拼接到执行的命令,没有做过滤。_cve-2023-33246
文章浏览阅读1.1k次。第一种方法 使用response.Redirect : Dim filename filename=request("file") response.Redirect "/images/" & filename & ".jpg" %> 第二种方法 使用server.createObject("ADODB.Stream"): Re_asp 隐藏 原图片地址