8.23Java远程方法中使用反射机制

8.23Java远程方法中使用反射机制

java.lang.reflect

  • Construct类获取构造方法信息

  • Method类获取成员方法信息

  • Field类获取成员变量信息


反射机制在网络编程中的应用

反射机制在网络编程中的应用,实现如何在客户端通过远程方法调用服务器端的方法。

步骤

  • 写一个HelloService接口,该接口具有 getTime() 和 echo() 方法

  • 创建一个 HelloServiceImpl 类并实现 HelloService 接口


需求是:

  • 客户端调用服务器端 Hello-ServiceImpl 类中的 getTime() 和 echo() 方法

实现方法:

客户端需要把调用的方法名、方法参数类型、方法参数值,以及方法所属的类名或接口名发送给服务器端。服务器端再调用相关对象的方法,然后把方法的返回值发送给客户端。

写一个Call类去实现:

package PracticeReview.RemoteCall;

/**
* Call类,实现反射的远程通信
* @since JDK 1.8
* @date 2021/08/23
* @author Lucifer
*/
public class Call {
   private static final long serialVersionUID = 6659953547331194808L;

   /*类名或者接口名*/
   private String className;
   /*方法名*/
   private String methodName;
   /*方法参数类型*/
   private Class[] paramType;
   /*方法参数值*/
   private Object[] params;

   // 表示方法的执行结果
   // 如果方法正常执行,则result为方法返回值,如果方法抛出异常,那么result为该异常。
   private Object result;
   public Call() {
  }
   public Call(String className, String methodName, Class[] paramType, Object[] params) {
       this.className = className;
       this.methodName = methodName;
       this.paramType = paramType;
       this.params = params;
  }

   public static long getSerialVersionUID() {
       return serialVersionUID;
  }

   public String getClassName() {
       return className;
  }

   public String getMethodName() {
       return methodName;
  }

   public Class[] getParamType() {
       return paramType;
  }

   public Object[] getParams() {
       return params;
  }

   public Object getResult() {
       return result;
  }

   public void setClassName(String className) {
       this.className = className;
  }

   public void setMethodName(String methodName) {
       this.methodName = methodName;
  }

   public void setParamType(Class[] paramType) {
       this.paramType = paramType;
  }

   public void setParams(Object[] params) {
       this.params = params;
  }

   public void setResult(Object result) {
       this.result = result;
  }

   public String toString() {
       return "className=" + className + "methodName=" + methodName;
  }
}

客户端为SimpleClient,服务端为SimpleServerSimpleClient调用SimpleServerHelloServicelmplecho()方法:

  1. SimpleClient 创建一个 Call 对象,它包含调用 HelloService 接口的 echo() 方法的信息。

  2. SimpleClient 通过对象输出流把 Call 对象发送给 SimpleServer。

  3. SimpleServer 通过对象输入流读取 Call 对象,运用反射机制调用 HelloServiceImpl 对象的 echo() 方法,把 echo() 方法的执行结果保存到 Call 对象中。

  4. SimpleServer 通过对象输出流把包含方法执行结果的 Call 对象发送给 SimpleClient。

  5. SimpleClient 通过对象输入流读取 Call 对象,从中获得方法执行结果。

package PracticeReview.RemoteCall;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
* 客户端实现类
* @since JDK 1.8
* @date 2021/08/23
* @author Lucifer
*/
public class SimpleClient {
   public void invoke() throws Exception {
       Socket socket = new Socket("localhost", 8000);
       OutputStream out = socket.getOutputStream();
       ObjectOutputStream oos = new ObjectOutputStream(out);
       InputStream in = socket.getInputStream();
       ObjectInputStream ois = new ObjectInputStream(in);
       // 创建一个远程调用对象
       Call call = new Call("ch12.HelloService", "echo", new Class[] { String.class }, new Object[] { "Java" });
       oos.writeObject(call); // 向服务器发送Call对象
       call = (Call) ois.readObject(); // 接收包含了方法执行结果的Call对象
       System.out.println(call.getResult());
       ois.close();
       oos.close();
       socket.close();
  }
}

服务端代码:

package PracticeReview.RemoteCall;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
* 服务端接收信息
* @since JDK 1.8
* @date 2021/08/23
* @author Lucifer
*/
public class SimpleServer {
   private Map remoteObjects = new HashMap(); // 存放远程对象的缓存
   /** 把一个远程对象放到缓存中 */
   public void register(String className, Object remoteObject) {
       remoteObjects.put(className, remoteObject);
  }
   public void service() throws Exception {
       ServerSocket serverSocket = new ServerSocket(8000);
       System.out.println("服务器启动.");
       while (true) {
           Socket socket = serverSocket.accept();
           InputStream in = socket.getInputStream();
           ObjectInputStream ois = new ObjectInputStream(in);
           OutputStream out = socket.getOutputStream();
           ObjectOutputStream oos = new ObjectOutputStream(out);
           Call call = (Call) ois.readObject(); // 接收客户发送的Call对象
           System.out.println(call);
           call = invoke(call); // 调用相关对象的方法
           oos.writeObject(call); // 向客户发送包含了执行结果的Call对象
           ois.close();
           oos.close();
           socket.close();
      }
  }
   public Call invoke(Call call) {
       Object result = null;
       try {
           String className = call.getClassName();
           String methodName = call.getMethodName();
           Object[] params = call.getParams();
           Class classType = Class.forName(className);
           Class[] paramTypes = call.getParamType();
           Method method = classType.getMethod(methodName, paramTypes);
           Object remoteObject = remoteObjects.get(className); // 从缓存中取出相关的远程对象
           if (remoteObject == null) {
               throw new Exception(className + "的远程对象不存在");
          } else {
               result = method.invoke(remoteObject, params);
          }
      } catch (Exception e) {
           result = e;
      }
       call.setResult(result); // 设置方法执行结果
       return call;
  }
   public static void main(String args[]) throws Exception {
       SimpleServer server = new SimpleServer();
       // 把事先创建的HelloServiceImpl对象加入到服务器的缓存中
       server.register("ch13.HelloService", new HelloServiceImpl());
       server.service();
  }
}

 

上一篇:预览在线的pdf


下一篇:Java框架的灵魂之注解