题目:
完成以下的功能:服务端有一个计算器,有加减两个方法,分别为:add(p1,p2),minus(p1,p2)。
创建Request类实现序列化接口,该类包含以下属性:
String methodName;//方法名
Object[] params;//方法参数列表。
将客户端发送method,p1,p2到服务端请求封装成request发到服务端。
服务端响应请求,将结果封装成response发送给客户端
Response 属性如下:
Object result;//方法调用结果
String msg;//成功则为success,是否则为failure;
思路:运用rpc 远程方法调用 包括动态代理、网络、序列化、反射
代码如下
package Test; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.ServerSocket; import java.net.Socket; public class MyServer { public static void main(String[] args) throws IOException, ClassNotFoundException, InvocationTargetException, IllegalAccessException { //开启9999监听端口进行监听 ServerSocket serverSocket = new ServerSocket(9999); //监听客户端的连接 Socket client = serverSocket.accept(); //创建用于接收客户端的对象输出和输入流--用于反序列化 ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream()); ObjectInputStream ois = new ObjectInputStream(client.getInputStream()); //接收客户端传过来的请求 Request request = (Request) ois.readObject(); // String methodName = request.getMethodName(); Object[] params = request.getParams(); //反射--第一步:获取类 Class<MyCalculatorImpl> clazz = MyCalculatorImpl.class; //由类名获取所有方法 Method[] methods = clazz.getDeclaredMethods(); //遍历方法数组 for (Method method : methods) { //判断方法数组中名字是否有请求中的方法名 if (method.getName().equals(methodName)) { //如果有则用该方法调用invoke方法--类似于创建一个MyCalculatorImpl对象调用该方法 Object res = method.invoke(new MyCalculatorImpl(), params); Response response = new Response(); response.setRes(res); response.setMag("success"); oos.writeObject(response); } } } }
package Test; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.Socket; //客户端 public class MyClient { public static void main(String[] args) throws IOException, ClassNotFoundException { Socket socket = new Socket("127.0.0.1", 9999); final ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); final ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); //类加载器 ClassLoader classLoader = MyClient.class.getClassLoader(); //定义一个接口 Class[] interfaces = {MyCalculator.class}; //创建一个代理处理类 InvocationHandler invocationHandler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); Request request = new Request(); request.setMethodName(name); request.setParams(args); //发送出去 oos.writeObject(request); //接收响应 Response response = (Response) ois.readObject(); return response.getRes(); } }; //生成一个真正的代理类 MyCalculator mycal = (MyCalculator) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); int res2 = mycal.minus(15, 7); System.out.println(res2); /*Request request = new Request(); request.setMethodName("add"); request.setParams(new Object[]{1,3}); oos.writeObject(request); Response response = (Response) ois.readObject(); System.out.println(response);*/ } }
package Test; //客户端的计算器接口 public interface MyCalculator { int add(int p1, int p2); int minus(int p1, int p2); }
package Test; //用作反射--服务器的计算器 //Impl是一个实现了某个接口的实现类 public class MyCalculatorImpl implements MyCalculator{ public int add(int p1, int p2) { return p1 + p2; } public int minus(int p1, int p2) { return p1 - p2; } }
package Test; import java.io.Serializable; //Request请求对象:方法名+方法参数 public class Request implements Serializable { //方法名 private String methodName; //方法参数数组 private Object[] params; public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public Object[] getParams() { return params; } public void setParams(Object[] params) { this.params = params; } }
package Test; import java.io.Serializable; //服务器给客户端的响应对象:结果+标示 public class Response implements Serializable { //结果 private Object res; //标示 private String mag; public Object getRes() { return res; } public void setRes(Object res) { this.res = res; } public String getMag() { return mag; } public void setMag(String mag) { this.mag = mag; } @Override public String toString() { return "Response{" + "res=" + res + ", mag='" + mag + '\'' + '}'; } }