Java在远程方法调用中运用反射机制

我们将介绍反射机制在网络编程中的应用,实现如何在客户端通过远程方法调用服务器端的方法。

假定在服务器端有一个 HelloService 接口,该接口具有 getTime() 和 echo() 方法,具体代码如下:

import java.util.Date;public interface HelloService {public String echo(String msg);public Date getTime();
}

在服务器上创建一个 HelloServiceImpl 类并实现 HelloService 接口。HelloServiceImpl 类的代码如下:

import java.util.Date;public class HelloServiceImpl implements HelloService {@Overridepublic String echo(String msg) {return "echo:" + msg;}@Overridepublic Date getTime() {return new Date();}
}

上述代码所示,在 HelloServiceImpl 类中对 echo() 方法和 getTime() 方法进行了重写。那么,客户端如何调用服务器端 Hello-ServiceImpl 类中的 getTime() 和 echo() 方法呢?

具体方法是:客户端需要把调用的方法名、方法参数类型、方法参数值,以及方法所属的类名或接口名发送给服务器端。服务器端再调用相关对象的方法,然后把方法的返回值发送给客户端。

为了便于按照面向对象的方式来处理客户端与服务器端的通信,可以把它们发送的信息用 Call 类来表示。一个 Call 对象表示客户端发起的一个远程调用,它包括调用的类名或接口名、方法名、方法参数类型、方法参数值和方法执行结果。

Call 类的实现代码如下:

import java.io.Serializable;public class Call implements Serializable {private static final long serialVersionUID = 6659953547331194808L;private String className; // 表示类名或接口名private String methodName; // 表示方法名private Class[] paramTypes; // 表示方法参数类型private Object[] params; // 表示方法参数值// 表示方法的执行结果// 如果方法正常执行,则result为方法返回值,如果方法抛出异常,那么result为该异常。private Object result;public Call() {}public Call(String className, String methodName, Class[] paramTypes, Object[] params) {this.className = className;this.methodName = methodName;this.paramTypes = paramTypes;this.params = params;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public String getMethodName() {return methodName;}public void setMethodName(String methodName) {this.methodName = methodName;}public Class[] getParamTypes() {return paramTypes;}public void setParamTypes(Class[] paramTypes) {this.paramTypes = paramTypes;}public Object[] getParams() {return params;}public void setParams(Object[] params) {this.params = params;}public Object getResult() {return result;}public void setResult(Object result) {this.result = result;}public String toString() {return "className=" + className + "methodName=" + methodName;}
}

假设客户端为 SimpleClient,服务器端为 SimpleServer。SimpleClient 调用 SimpleServer 的 HelloServiceImpl 对象中 echo() 方法的流程如下:

1 . SimpleClient 创建一个 Call 对象,它包含调用 HelloService 接口的 echo() 方法的信息。

2 . SimpleClient 通过对象输出流把 Call 对象发送给 SimpleServer。

3 . SimpleServer 通过对象输入流读取 Call 对象,运用反射机制调用 HelloServiceImpl 对象的 echo() 方法,把 echo() 方法的执行结果保存到 Call 对象中。

4 . SimpleServer 通过对象输出流把包含方法执行结果的 Call 对象发送给 SimpleClient。

5 . SimpleClient 通过对象输入流读取 Call 对象,从中获得方法执行结果。

首先来看看客户端程序 SimpleClient 类的实现代码。

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;
import java.io.*;
import java.net.*;
import java.util.*;public class SimpleClient {public void invoke() throws Exception {Socket socket = new Socket("localhost", 8000);OutputStream out = socket.getOutputStream();ObjectOutputStream oos = new ObjectOutputStream(out);InputStream in = socket.getInputStream();ObjectInputStream ois = new ObjectInputStream(in);// 创建一个远程调用对象Call call = new Call("ch12.HelloService", "echo", new Class[] { String.class }, new Object[] { "Java" });oos.writeObject(call); // 向服务器发送Call对象call = (Call) ois.readObject(); // 接收包含了方法执行结果的Call对象System.out.println(call.getResult());ois.close();oos.close();socket.close();}public static void main(String args[]) throws Exception {new SimpleClient().invoke();}
}

如上述代码所示,客户端 SimpleClient 类的主要作用是建立与服务器的连接,然后将带有调用信息的 Call 对象发送到服务器端。

服务器端 SimpleServer 类在收到调用请求之后会使用反射机制动态调用指定对象的指定方法,再将执行结果返回给客户端。

SimpleServer 类的实现代码如下:

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;public class SimpleServer {private Map remoteObjects = new HashMap(); // 存放远程对象的缓存/** 把一个远程对象放到缓存中 */public void register(String className, Object remoteObject) {remoteObjects.put(className, remoteObject);}public void service() throws Exception {ServerSocket serverSocket = new ServerSocket(8000);System.out.println("服务器启动.");while (true) {Socket socket = serverSocket.accept();InputStream in = socket.getInputStream();ObjectInputStream ois = new ObjectInputStream(in);OutputStream out = socket.getOutputStream();ObjectOutputStream oos = new ObjectOutputStream(out);Call call = (Call) ois.readObject(); // 接收客户发送的Call对象System.out.println(call);call = invoke(call); // 调用相关对象的方法oos.writeObject(call); // 向客户发送包含了执行结果的Call对象ois.close();oos.close();socket.close();}}public Call invoke(Call call) {Object result = null;try {String className = call.getClassName();String methodName = call.getMethodName();Object[] params = call.getParams();Class classType = Class.forName(className);Class[] paramTypes = call.getParamTypes();Method method = classType.getMethod(methodName, paramTypes);Object remoteObject = remoteObjects.get(className); // 从缓存中取出相关的远程对象if (remoteObject == null) {throw new Exception(className + "的远程对象不存在");} else {result = method.invoke(remoteObject, params);}} catch (Exception e) {result = e;}call.setResult(result); // 设置方法执行结果return call;}public static void main(String args[]) throws Exception {SimpleServer server = new SimpleServer();// 把事先创建的HelloServiceImpl对象加入到服务器的缓存中server.register("ch13.HelloService", new HelloServiceImpl());server.service();}
}

由于这是一个网络程序,首先需要运行服务器端 SimpleServer,然后再运行客户端 SimpleClient。运行结果是在客户端看到输出“echoJava”,这个结果是服务器端执行 HelloServicelmpl 对象的 echo() 方法的返回值。下图显示了 SimpleClient 与 SimpleServer 的通信过程。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/564731.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安捷伦频谱仪的使用方法图解_频谱仪的简单操作使用方法lbrack;1rsqb;

R3131A频谱仪简单操作使用方法一.R3131A频谱仪简介。R3131A频谱仪是日本ADVANTEST公司的产品,用于测量高频信号,可测量的频率范围为9K—3GHz。对于GSM手机的维修,通过频谱仪可测量射频电路中的以下电路信号, (维修人员可以通过对所…

多元时间序列分析 —— 因果检验

目录 因果检验 因果关系的识别 例 Granger 因果关系定义 两变量之间的4种因果关系 Granger因果检验 1.假设条件 2.检验统计量 例 进行Granger因果检验应该注意的问题 因果检验 因果关系的识别 对于多元时间序列而言,如果能找到对响应变量有显.著影响的输…

华为仿苹果字体_华为mate40系列再次霸榜DXO,网友:无敌是多么寂寞

阅读本文前,请您先点击上面的蓝色字体,再点击“关注”,这样您就可以免费收到最新内容了。每天都有分享,完全是免费订阅,请放心关注。声明:本文转载自网络,如有侵权,请在后台留言联系…

Java常见异常处理

异常(exception)是在运行程序时产生的一种异常情况,已经成为了衡量一门语言是否成熟的标准之一。 异常简介 Java 中的异常又称为例外,是一个在程序执行期间发生的事件,它中断正在执行程序的正常指令流。为了能够及时…

干预分析 + 伪回归

目录 干预分析 干预分析的定义 干预分析的产生背景 干预分析的实质 干预分析步骤 步骤一 步骤二 步骤三 步骤四 步骤五 步骤六 干预机制的选择 伪回归 定义 伪回归随机模拟试验 伪回归产生原因 干预分析 干预分析的定义 时间序列常常受到某些外部事件的影响…

R如何安装MSBVAR包!!!请看这里!!

目录 1.MSBVAR介绍 2.为何R上安装失败 3.解决方案 1.MSBVAR介绍 MSBVAR: 估计贝叶斯向量自回归模型和贝叶斯结构向量自回归模型,也可以用于时间序列的因果检验。 2.为何R上安装失败 MSBVAR现在不属于R中的库,属于第三方安装库,并且它在…

easy excel根据行列excel_Excel函数如何根据地级市匹配所在省份计算快递费用

前些日子一个学员问的关于excel计算快递费的问题,office小超老师觉得很有代表性。在这里和大家分享一下具体处理快递费的处理流程。在她的这个案例中,订单信息地区仅为各个地级市,现在的问题就是要根据不同的地级市和各个地区不同的快递费用&…

Java中Error和Exception的异同

Error(错误)和 Exception(异常)都是 java.lang.Throwable 类的子类,在 Java 代码中只有继承了 Throwable 类的实例才能被 throw 或者 catch。 Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类&#x…

智能计算之遗传算法(GA)介绍

目录 1. 简介 2. GA思想来源及建立过程 3. 研究发展 4. GA的基本结构 5. GA的实现流程 (1) 染色体编​辑 (2) 群体的初始化 (3) 适应值评价 (4) 选择算子(父体选择) (5) 交配算子(杂交算子) (6) 变异算子 (7) 算法流程 6. 实例举例 7. 遗传算法的改进 (1) 算子的…

sublimetext3插件安装_sublime text 3 交互python

爱折腾的我最近在用sublime text 3 写python,但是原生态的编译模式不支持交互。在网上找了许多资料,想要可以交互运行python,大都需要sublimeREPL这个插件,我不想用这个插件。在多次摸索过后找到了如下解决方案,在此记…

如何用手机打开dcm格式图片_压缩图片用这个神奇吧(电脑版)

一码不扫,可以扫天下?Light Image Resizer是将数码照片和图像存在电脑中,并希望重新调整图片大小,压缩,转换,创建备份,导入或组织图片的人们设计的完美工具。Light Image Resizer 专业的图像缩放…

智能计算之神经网络(BP)介绍

目录 1. 神经网络流行原因 2. 人工神经网络定义 3. 人工神经网络的学习能力 4. 人工神经网络的基本原理 5. 神经网络的研究进展 6. 神经网络的典型结构 6.1 单层感知器网络 6.2 前馈型网络 6.3 前馈内层互联网络 6.4 反馈型网络 6.5 全互联网络 7. 神经网络的学习算…

python系统关键字_Python基础教程 - global关键字及全局变量的用法

Python中global关键字主要作用是声明变量的作用域。 在C语言中,由于变量一定是先声明,后使用,所以我们可以清楚的知道,现在使用的变量是全局还是局部,比如: int a 5; void test(void) { a 1; // 没有先声…

如何查看keepalived版本号_Keepalived介绍 , 配置说明 , 及实际应用

1. Keepalived介绍Keepalived是一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP单点故障,类似的工具还有heartbeat、corosync、pacemaker。但是它一般不会单独出现,而是与其它负载均衡技术(如lvs、haproxy、nginx)一起工作来达到…

智能计算之神经网络(Hopfield网络-DHNN,CHNN )介绍

目录 1. 神经网络受欢迎的原因 2. 人工神经网络定义 3. 人工神经网络的学习能力 4. 人工神经网络的基本原理 5. 神经网络的研究进展 6. 神经网络的典型结构 6.1 单层感知器网络 6.2 前馈型网络 6.3 前馈内层互联网络 6.4 反馈型网络 6.5 全互联网络 7. 神经网络的学…

用python画渐变的圆_使用numpy绘制圆形渐变

由于对称性,实际上只需要计算图像256*256的四分之一,即64*64,然后将其逐块旋转90度,然后将它们组合起来。这样,总时间是计算256256像素的1/4倍。在 以下是示例。在import numpy as np import matplotlib.pyplot as plt…

发那科程序全部输出_如何拷贝FANUC系统全部程序

在SETTING画面复I/O通道一项中设定I/O4(或者制20#参数改为4),将存储卡(插在机床的面板上的PCMCIA接口里。选择编辑模式,程序钥匙锁打开,全部程序预览页面(列表),点击(操作),点击右扩展键,点击(F输出)&#…

计算平均成绩

根据用户输入的总人数和总成绩计算平均成绩。要求程序能够处理总人数或者总成绩不是数字时的情况。 使用多重 catch 语句时,Java 虚拟机会把实际拋出的异常对象依次和各个 catch 代码块中声明的异常类型匹配,如果异常对象为某个异常类型或者其子类的实例…

智能计算之蚁群算法(ACO)介绍

目录 1. 简介 2. 基本思想 3. 研究进展 4. 基本流程 (1)路径构建 (2)信息素更新 ​5. 应用举例 6. 改进版 6.1 精华蚂蚁系统 6.2 基于排列的蚂蚁系 6.3 最大最小蚂蚁系 6.4 蚁群系统 7. 参数设置​编辑 8. 练习题 …

Java try catch finally语句

在实际开发中,根据 try catch 语句的执行过程,try 语句块和 catch 语句块有可能不被完全执行,而有些处理代码则要求必须执行。例如,程序在 try 块里打开了一些物理资源(如数据库连接、网络连接和磁盘文件等&#xff09…