题目:
完成以下的功能:服务端有一个计算器,有加减两个方法,分别为: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 + '\'' +
'}';
}
}