涉及的知识点:动态代理,网络IO,序列化(RPC序列化框架,了解JDK序列化的缺点),反射,网络协议(通过哪种协议来传输数据),以下是RPC简单实现,可针对各个环节优化,比如IO可以采用NIO,序列化可以选择hessian。
客户端:
/**
* 模拟客户端
*/
public class Client {
public static void main(String[] args) throws IOException {
UserService userService = new UserServiceImpl();
UserService userServiceProxy = (UserService) ProxyDemo.getProxy(userService.getClass());
User user = userServiceProxy.findUserById(123);
System.out.println(user);
StudentService studentService = new StudentServiceImpl();
StudentService studentServiceProxy = (StudentService) ProxyDemo.getProxy(studentService.getClass());
Student student = studentServiceProxy.findStudentByIdAndName(789,"lisi");
System.out.println(student);
}
}
/**
* 动态代理,获取代理的对象
*/
public class ProxyDemo {
public static Object getProxy(Class c){
// 生成代理对象
Object object = Proxy.newProxyInstance(c.getClassLoader(), c.getInterfaces(), new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 1.与服务端建立连接,发送调用的服务相关信息
Socket socket = new Socket("127.0.0.1",9999);
// 发送数据到服务端
System.out.println("发送数据到服务端");
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
// 服务名
oos.writeUTF(c.getName());
// 方法名
oos.writeUTF(method.getName());
// 方法参数类型
oos.writeObject(method.getParameterTypes());
// 方法参数
oos.writeObject(args);
oos.flush();
// 2.接收服务端的信息
System.out.println("接收服务端数据");
/* ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Object o = ois.readObject();*/
// 自定义反序列化(Hessian也需要实现Serializable接口)
HessianInput hi = new HessianInput(socket.getInputStream());
Object o = hi.readObject();
oos.close();
hi.close();
socket.close();
return o;
}
});
return object;
};
}
服务端:
/**
* 模拟服务端
*/
public class Server {
public static boolean isServerRunning = true;
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
ServerSocket serverSocket = new ServerSocket(9999);
while (isServerRunning){
Socket s = serverSocket.accept();
System.out.println("《《《开始处理客户端的请求》》》");
process(s);
s.close();
}
serverSocket.close();
}
/**
* 处理任意接口,任意方法(包括重载),返回任意对象
*/
private static void process(Socket s) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
// 1,接收客户端数据
System.out.println("接收客户端数据");
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
String className = ois.readUTF();
String methodName = ois.readUTF();
Class[] getParameterTypes = (Class[]) ois.readObject();
Object[] args = (Object[]) ois.readObject();
// 2,返回数据给客户端
/**
* 可以通过Spring的注入获取到methodName的实例(一般服务暴露是URL的形式暴露的,
* 这里就涉及服务端通过URL找到具体的执行方法,类似于SpringMVC的请求执行流程,
* 具体看服务端怎么实现)
*/
Object service = Class.forName(className).newInstance();
Method method = service.getClass().getMethod(methodName,getParameterTypes);
Object object = method.invoke(service,args);
System.out.println("返回客户端数据");
/* ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
oos.writeObject(object);
oos.flush();*/
// 自定义序列化(Hessian也需要实现Serializable接口)
OutputStream os = (OutputStream) s.getOutputStream();
HessianOutput ho = new HessianOutput(os);
ho.writeObject(object);
ho.flush();
ho.close();
}
}
public class User implements Serializable {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args) {
System.out.println(User.class.getName());
}
}
public class UserServiceImpl implements UserService{
@Override
public User findUserById(int id) {
return new User("demo",id);
}
}
public class Student implements Serializable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class StudentServiceImpl implements StudentService {
@Override
public Student findStudentByIdAndName(int id,String name) {
return new Student(name,id);
}
}
参考: