【2022.10.10】基于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代码
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代码
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();
}
}
运行结果截图

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库