注:本文参照孙卫琴编写的<<网络编程详解>>
一、首先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、将执行的结果返回给客户端。