The use of Java reflection mechanism in a remote method invocation

We will introduce the application reflection in network programming, how to call a server-side implementation of the client by remote methods.

Assuming a HelloService server interface, the interface having getTime () and echo () method, the specific code is as follows:

import java.util.Date;

public interface HelloService {
    public String echo(String msg);

    public Date getTime();
}

HelloServiceImpl create a class on the server and implement HelloService interface. HelloServiceImpl class code as follows:

import java.util.Date;

public class HelloServiceImpl implements HelloService {
    @Override
    public String echo(String msg) {
        return "echo:" + msg;
    }

    @Override
    public Date getTime() {
        return new Date();
    }
}

As shown in the above code in the class of HelloServiceImpl echo () method and the getTime () method has been rewritten. So, how to call the client server Hello-ServiceImpl class getTime () and echo () methods?

The specific method is : the class or interface name sending client needs to invoke the method name, method parameter type, the parameter value method, and a method belongs to the server. Server-side method and then call the relevant object, and then the return value of the method is sent to the client.

To facilitate object-oriented manner according to handle communications client and server, information can be transmitted to them by the Call class represented. A Call object represents a remote call initiated by the client, which includes calling a class or interface name, the method name, parameter types, methods, parameters and methods of execution results.

Call class codes are as follows:

import java.io.Serializable;

public class Call implements Serializable {

    private static final long serialVersionUID = 6659953547331194808L;

    private String className; // 表示类名或接口名
    private String methodName; // 表示方法名
    private Class[] paramTypes; // 表示方法参数类型
    private Object[] params; // 表示方法参数值

    // 表示方法的执行结果
    // 如果方法正常执行,则result为方法返回值,如果方法抛出异常,那么result为该异常。
    private Object result;

    public Call() {
    }

    public Call(String className, String methodName, Class[] paramTypes, Object[] params) {
        this.className = className;
        this.methodName = methodName;
        this.paramTypes = paramTypes;
        this.params = params;
    }

    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;
    }

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

Assume that the client is SimpleClient, the server is SimpleServer. HelloServiceImpl objects SimpleClient call flow in SimpleServer echo () method is as follows:

1. SimpleClient create a Call object containing information call HelloService interface echo () method.

2. SimpleClient stream output through the object to send the Call object SimpleServer.

3. SimpleServer Call object by reading the object input stream, using the reflection echo HelloServiceImpl object call () method to save the execution results echo () method of the Call object.

4. SimpleServer SimpleClient through the object to send the output stream comprises performing the method results Call object.

5. SimpleClient Call object by reading the input stream objects, a method for obtaining an execution result therefrom.

First, let's look at the code that implements the client program SimpleClient class.

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;
import java.io.*;
import java.net.*;
import java.util.*;

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();
    }

    public static void main(String args[]) throws Exception {
        new SimpleClient().invoke();
    }
}

As shown in the code above, the main role is client SimpleClient classes establish a connection with the server, and then call the Call object with the information transmitted to the server.

SimpleServer class server after receiving the call request uses reflection to invoke the specified method of dynamically specified object, and then returns the execution result to the client.

SimpleServer class codes are as follows:

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;

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.getParamTypes();
            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();
    }
}

Since this is a web application, you first need to run server-side SimpleServer, and then run the client SimpleClient. The result is running on the client to see the output "echoJava", the result is the echo server-side implementation HelloServicelmpl object () method's return value. The following figure shows the communication process SimpleClient with SimpleServer.
Here Insert Picture Description

Published 457 original articles · won praise 94 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_45743799/article/details/104728769