基于java反射的远程方法调用demo

描述

  • 客户端向服务器发送要调用的对象和方法名,服务器找到对应方法并调用执行

实现

  • 客户端将类名、方法名和参数封装到可调用对象中,通过socket的对象流将可调用对象发送到服务器上,服务器通过已建立的HashMap找到要调用的目标对象,通过Class.forName方法找到对应的class对象,通过getMethod方法找到要调用的方法,通过method.invoke进行调用

结构

  • 共四个类,Call.java封装了可调用对象
  • HelloRemote.java封装了目标对象
  • Client.java和Server.java分别处理客户端和服务器业务

Call.java代码

import java.io.Serializable;

public class Call implements Serializable{
    private static final long serialVersionUID = 6597953547331194808L;
    private String className;
    private String methodName;
    private Class [] paramTypes;
    private Object [] params;
    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 String getMethodName(){
        return methodName;
    }

    public Class[] getParamTypes(){
        return paramTypes;
    }

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

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

    public Object getResult(){
        return result;
    }

    public String toString(){
        return "[来自客户端的消息] 小王同学你好,我是" + params[0] + ",向你请求的类名是:" + className + ",方法名是:" + methodName;
    }
}

Client.java代码

/* 利用反射机制实现远程调用
 * 一、客户端
 * 1.定义一个Call类,用来告诉服务端要调用的方法和参数,以及接收返回结果
 * 2.定义一个Client类,通过socket将call对象发送到服务器,并接收返回的call对象
 */
import java.io.*;
import java.net.*;
import java.util.*;

public class Client{
    public void invoke(String name) 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("HelloRemote", "Hello", new Class[] {String.class}, new String[] {name});
        oos.writeObject(call);
        call = (Call) ois.readObject();
        System.out.println(call.getResult());

        ois.close();
        oos.close();
        socket.close();
    }

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

HelloRemote.java代码

import java.util.Date;
import java.text.SimpleDateFormat;

public class HelloRemote {
    public String Hello(String name){
        Date now = new Date();
        SimpleDateFormat f = new SimpleDateFormat("现在是" + "yyyy年MM月dd日HH点mm分ss秒");
        String time = f.format(now);
        return "[来自服务端的消息] " + name + "你好,我是小王," + time + ",欢迎和我建立连接^_^";
    }
}

Server.java代码

/* 利用反射机制实现远程调用
 * 一、服务端
 * 1.定义一个需要调用的类HelloRemote
 * 2.定义一个Server类,将HelloRemote对象写入到缓存中,开启socket监听
 * 3.接收到call对象后,获取要调用的类名,通过Class.forName方法获取要调用的class对象
 * 4.获取要调用的方法名和参数类型,通过getMethod方法获取要调用的方法
 * 5.从缓存中读取要调用的对象,并获取要调用的参数列表,通过method.invoke方法,完成目标方法调用,并将结果写到call对象的result属性
 * 6.将call对象写到socket流中,返回给客户端
 */

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

public class Server {
    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 = invoke(call);
            oos.writeObject(call);
            ois.close();
            oos.close();
            socket.close();
        }
    }

    public Call invoke(Call call) {
        Object result = null;
        try {
            String className = call.getClassName();
            String methodName = call.getMethodName();
            Class[] paramTypes = call.getParamTypes();
            Object[] params = call.getParams();
            Class classType = Class.forName(className);
            Method method = classType.getMethod(methodName, paramTypes);
            Object remoteObject = remoteObjects.get(className);
            if (remoteObject == null) {
                throw new Exception(className + "的远程对象不存在");
            } else {
                System.out.println(call);
                result = method.invoke(remoteObject, params);
            }
        }
        catch (Exception e){
            result = e;
        }
        call.setResult(result);
        return call;
    }

    public static void main(String [] args) throws Exception {
        Server server = new Server();
        server.register("HelloRemote", new HelloRemote());
        server.service();
    }
}

运行结果截图

posted @ 2022-10-19 09:07  z5onk0  阅读(122)  评论(0编辑  收藏  举报