The reflection of Java language (3)

在远程方法调用中也经常使用到java的反射机制,一下举个远程方法调用的例子,假定在SimpleServer 服务器端创建了一个HelloServiceImpl对象,它具有getTime()和echo()方法。HelloServiceImpl类实现了HelloService接口。如例下例所示分别是HelloService接口和HelloServiceImpl类的代码:

 

import java.util.Date;

public interface HelloService {
	public String echo(String msg);
	public Date getTime();
}

 

import java.util.Date;

public class HelloServiceImpl implements HelloService{

	@Override
	public String echo(String msg) {
		// TODO Auto-generated method stub
		return "echo: "+ msg;
	}

	@Override
	public Date getTime() {
		// TODO Auto-generated method stub
		return new Date();
	}
	
}
 

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

 

import java.io.Serializable;
import java.util.Arrays;

public class Call implements Serializable {
	private String className;
	
	private String methodName;
	
	private Class[] paramTypes;
	
	private Object[] params;
	
	private Object result;
	
	public Call(){}

	public Call(String className, String methodName, Class[] paramTypes,
			Object[] params) {
		super();
		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;
	}

	@Override
	public String toString() {
		return "Call [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对象,从中获得方法执行结果。如下例所示分别是SimpleServer 和SimpleClient 的源程序。

 

 

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

public class SimpleClient {
	public void invoke() throws Exception {
		Socket socket = new Socket("localhost", 8008);
		OutputStream out = socket.getOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(out);

		InputStream in = socket.getInputStream();
		ObjectInputStream ois = new ObjectInputStream(in);

		Call call = new Call("t0428.HelloService", "echo",
				new Class[] { String.class }, new Object[] { "Hello" });

		oos.writeObject(call);
		call = (Call) ois.readObject();
		System.out.println(call.getResult());

		ois.close();
		oos.close();
		socket.close();
	}

	public static void main(String args[]) throws Exception {
		new SimpleClient().invoke();
	}
}

 import java.lang.reflect.Method;

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

public class SimpleServer {
	private Map remoteObjects = new HashMap();

	public void register(String className, Object remoterObject) {
		remoteObjects.put(className, remoterObject);
	}

	public void service() throws Exception {
		ServerSocket serverSocket = new ServerSocket(8008);

		System.out.println("server is started");

		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();
			System.out.println("server :"+ call);
			
			call = invoke(call);
			oos.writeObject(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[] paramTpyes = call.getParamTypes();
			
			Method method = classType.getMethod(methodName, paramTpyes);
			
			Object remoteObject = remoteObjects.get(className);
			
			if(remoteObject == null){
				throw new Exception(className + " the remote object is not existed!");
			}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 ss = new SimpleServer();
		ss.register("t0428.HelloService", new HelloServiceImpl());
		ss.service();
	}
}

你可能感兴趣的:(java,.net,socket)