`

java 反射机制(二)远程方法调用

阅读更多
假定在SimpleServer 服务器端创建了一个HelloServiceImpl对象,它具有getTime()
和echo()方法。HelloServiceImpl类实现了HelloService接口
远程方法调用先定义接口及其实现,
package reflection.rmi;

import java.util.Date;

public interface HelloService {//服务接口
	public String echo(String msg);

	public Date getTime();
}

package reflection.rmi;

import java.util.Date;

public class HelloServiceImpl implements HelloService { //服务类
	public String echo(String msg) {
		return "echo:" + msg;
	}

	public Date getTime() {
		return new Date();
	}
}

SimpleClient客户端如何调用服务器端的HelloServiceImpl对象的getTime()和echo()
方法呢?显然,SimpleClient客户端需要把调用的方法名、方法参数类型、方法参数值,
以及方法所属的类名或接口名发送给SimpleServer,SimpleServer 再调用相关对象的方
法,然后把方法的返回值发送给SimpleClient。
为了便于按照面向对象的方式来处理客户端与服务器端的通信,可以把它们发送
的信息用Call 类(如例程10-8所示)来表示。一个Call对象表示客户端发起的一个远
程调用,它包括调用的类名或接口名、方法名、方法参数类型、方法参数值和方法执
行结果。
例程10-8Call.java
package reflection.rmi;

import java.io.*;

public class Call implements Serializable { // 可串口化的对象
	private String className; // 表示类名或接口名
	private String methodName; // 表示方法名
	private Class[] paramTypes; // 表示方法参数类型,用于getMethod方法
	private Object[] params; // 表示方法参数值,用于invoke方法
	// 表示方法的执行结果
	// 如果方法正常执行,则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 端的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对象,从中获得方法执行结果。
如例程10-9 和例程10-10 所示分别是SimpleServer 和SimpleClient 的源程序。

客户端代码例程10-10 SimpleClient.java
package reflection.rmi;

import java.io.*;
import java.net.*;
import java.util.*;

public class SimpleClient {
	public void invoke() throws Exception {
		Socket socket = new Socket("localhost", 8888);
		
		OutputStream out = socket.getOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(out);
		InputStream in = socket.getInputStream();
		ObjectInputStream ois = new ObjectInputStream(in);
		
		// Call call=new Call("remotecall.HelloService","getTime",
		// new Class[]{},new Object[]{});
		Call call = new Call("reflection.rmi.HelloService", "echo",
				new Class[] { String.class }, new Object[] { "Hello" });
		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();
	}
}


服务器端代码:例程10-9 SimpleServer.java
package reflection.rmi;

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(8888);
		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); // toString()方法

			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("reflection.rmi.HelloService", new HelloServiceImpl());
		server.service();
	}
}


先运行命令“java reflection.rmi.SimpleServer”,再运行命令“java reflection.rmi.SimpleClient”,SimpleClient 端将打印“echo:Hello”。该打印结果是服务器端执行HelloServiceImpl 对象的echo()方法的返回值
如下图所示:







  • 大小: 9.3 KB
  • 大小: 6.5 KB
  • 大小: 5.8 KB
分享到:
评论

相关推荐

    java反射机制.pdf

    本章首先介绍了Java Reflection API的用法,然后介绍了一...这个例子中客户端能够远程调用服务器端的一个对象的方法。服务器端采用了反射机制提供 的动态调用方法的功能,而客户端则采用了反射机制提供的动态代理功能。

    Java语言的反射机制.rar

    本章首先介绍了Java Reflection API的用法,然后介绍了一个远程方法调用的例子,在这个例子中客户端能够远程调用服务器端的一个对象的方法。服务器端采用了反射机制提供的动态调用方法的功能,而客户端则采用了反射...

    Java_Reflection_Programming.rar_Agent_java programming_反射

    详细讲解Java的反射机制,包括Reflection API、在远程方法调用中运用反射机制、代理模式,后面还有一些练习和答案

    Java使用传统socket手写的远程RPC框架调用框架

    利用Java开发的socket客户端和服务端远程RPC通信框架,利用了动态代理和反射技术,

    java api最新7.0

    java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java.nio ...

    JAVA_API1.6文档(中文)

    java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java....

    新生命团队基础框架X组件,包括网络、数据库、安全、多线程、反射、序列化、模版引擎、服务代理、远程过程调用等模块

    新生命团队基础框架X组件,包括网络、数据库、安全、多线程、反射、序列化、模版引擎、服务代理、远程过程调用等模块,包括Web后台魔方、超级码神工具、消息队列等子系统,支持Mono/Android/iOS。

    Java 1.6 API 中文 New

    java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java.nio ...

    Java2核心技术.part5

    Java2核心技术第I卷.基础知识 目录: 译者序 ...5.7 远程方法调用与SOAP 第6章 高级Swing 第7章 高级AWT 第8章 JavaBean构件 第9章 安全 第10章 国际化 第11章 本地方法 第12章 XML 第13章 注释

    JavaRpc:JAVA RPC实现,基于动态代理与反射

    RPC全程Remote Procedure Call Protocol,即远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序...

    JavaAPI1.6中文chm文档 part1

    java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java....

    java 编程入门思考

    7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6 内部类 7.6.1...

    Java初学者入门教学

    7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6 内部类 7.6.1...

    java联想(中文)

    7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6 内部类 7.6.1...

    Java2核心技术.part3

    Java2核心技术第I卷.基础知识 目录: 译者序 ...5.7 远程方法调用与SOAP 第6章 高级Swing 第7章 高级AWT 第8章 JavaBean构件 第9章 安全 第10章 国际化 第11章 本地方法 第12章 XML 第13章 注释

    JAVA_Thinking in Java

    7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6 内部类 7.6.1...

    Java2核心技术.part1

    Java2核心技术第I卷.基础知识 目录: 译者序 前言 ...5.7 远程方法调用与SOAP 第6章 高级Swing 第7章 高级AWT 第8章 JavaBean构件 第9章 安全 第10章 国际化 第11章 本地方法 第12章 XML 第13章 注释

    Java2核心技术.part6

    Java2核心技术第I卷.基础知识 目录: 译者序 ...5.7 远程方法调用与SOAP 第6章 高级Swing 第7章 高级AWT 第8章 JavaBean构件 第9章 安全 第10章 国际化 第11章 本地方法 第12章 XML 第13章 注释

Global site tag (gtag.js) - Google Analytics