反射模拟远程调用

注:本文参照孙卫琴编写的<<网络编程详解>>

一、首先Demo

1、Call辅助类,进行数据传输,Soket通信载体

package com.yezi.remotecall;

import java.io.Serializable;

/**远程调用的发送数据*/
public class Call implements Serializable{
	private String className; //调用的类名称
	private String methodName; //调用的方法名称
	private Class[] paramTypes; //调用的方法的参数类型
	private Object[] params; //调用的方法传递的参数
	private Object result; //返回的结果
	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;
	}
}


2、要操作的对象

package com.yezi.remotecall;

import java.io.Serializable;

public class Student implements Serializable{
	@Override
	public String toString() {
		return sno+"---"+sname;
	}
	private static final long serialVersionUID = 1914058079545166552L;
	private String sno;
	private String sname;
	public String getSno() {
		return sno;
	}
	public void setSno(String sno) {
		this.sno = sno;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
}


3、接口类,进行公开给客户端的StudentService

package com.yezi.remotecall;

public interface StudentService {
	
	/**添加用户*/
	public Student addStudent(Student student);
}


4、实现类StudentServiceImpl

package com.yezi.remotecall;

public class StudentServiceImpl implements StudentService{

	@Override
	public Student addStudent(Student student) {
		System.out.println("insert into student--sname:"+student.getSname()+"--"+student.getSno());
		student.setSname("insertSname");
		student.setSno("insertSno");
		return student;
	}
}

5、RemoteServer类

package com.yezi.remotecall;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RemoteServer extends ThreadPoolExecutor{
	
	/**存放接口名字和实现类的对象*/
	private Map<String,Object> remoteSerMap;
	
	private ServerSocket serverSocket;
	
	public RemoteServer(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue) throws Exception {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
		remoteSerMap = new HashMap<String, Object>();
		register("com.yezi.remotecall.StudentService",new StudentServiceImpl());
		acceptServer();
	}
	
	public void acceptServer() throws Exception{
		System.out.println("start server ...");
		serverSocket = new ServerSocket(8889);
		while(true){
			Socket socket = serverSocket.accept();
			execute(new InvokeThread(socket));
		}
	}
	
	public Object readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
		Object object = in.readObject();
		return object;
	}
	
	/***
	 * 模拟加载注册实现
	 * @param name 接口名称
	 * @param object 接口的实现类
	 */
	private void register(String name,Object object){
		remoteSerMap.put(name,object);
	}
	
	public static void main(String[] args) throws Exception {
		new RemoteServer(3,4,6,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(2));
	}
	
	private void writeObject(ObjectOutputStream out,Object obj) throws IOException{
		out.writeObject(obj);
		out.flush();
	}
	
	class InvokeThread implements Runnable{
		private Socket socket;
		public InvokeThread(Socket socket) {
			this.socket = socket;
		}
		@Override
		public void run() {
			Call resCall = null;
			ObjectInputStream in = null;
			ObjectOutputStream out = null;
			try {
				in = new ObjectInputStream( socket.getInputStream());
				Call call = (Call) readObject(in);
				Object object = remoteSerMap.get(call.getClassName());
				resCall =  new Call();
				resCall.setClassName(call.getClassName());
				resCall.setMethodName(call.getMethodName());
				resCall.setParams(call.getParams());
				resCall.setParamTypes(call.getParamTypes());
				Class<?> classType = Class.forName(call.getClassName());
				Method method =  classType.getMethod(call.getMethodName(),call.getParamTypes());
				if(method==null){
					resCall.setResult("不存在该方法");
				}
				resCall.setResult(method.invoke(object,call.getParams()));
				//写出该对象
				out = new ObjectOutputStream(socket.getOutputStream());
				writeObject(out,resCall);
			} catch (Exception e) {
				resCall.setResult(e);
			} finally{
				try {
					if(out!=null){
						out.close();
						out=null;
					}
					if(in!=null){
					    in.close();
					    in=null;
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}


6、客户端ClientTest

package com.yezi.remotecall;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class ClientTest {
	
	private Socket socket;  //发送的socket
	
	public Call callRemoetMethod(Call call ) throws IOException, ClassNotFoundException{
		ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
		//发送数据请求到服务器中
		out.writeObject(call);
		out.writeObject(null);
		out.flush();
		//读取服务器的数据
		ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
		Call resultCall = (Call) in.readObject();
		out.close();
		in.close();
		return resultCall;
	}
	
	public ClientTest() throws IOException {
		socket = new Socket("127.0.0.1",8889);
	}
	
	public static void main(String[] args) throws Exception {
		Call call = new Call();
		call.setClassName("com.yezi.remotecall.StudentService");
		call.setMethodName("addStudent");
		Student student = new Student();
		student.setSname("xxxxx");
		student.setSno("ttttttz");
		call.setParams(new Object[]{student});
		call.setParamTypes(new Class[]{Student.class});
		call.setResult(null);
		Call resultCall = new ClientTest().callRemoetMethod(call); 
		System.out.println(resultCall.getResult());
	}
}


二、解释

1、Call类是由客户端请求的辅助类,用户发送请求的类名和参数给服务器。

2、服务器通过解析Call类,来取对应的实现类(使用map集合),采用反射调用克服端请求的方法。

3、将执行的结果返回给客户端。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值