服务器通过socket获取到请求url(socket包含ip、端口号)。通过反射机制获取类中的方法及参数类型,然后使用url实例化一个类的对象,用该对象执行对应的方法。
客户端,首先获取服务器的ip地址及端口号。然后给服务器传送一个url,要调用的方法名及要传的参数。再通过同一端口获取执行结果。下面是源码:
服务端:
StartUp:
public class StartUp {
public static final int port = 9001;
public static void main(String[] args) {
exportRpc();
}
private static void exportRpc() {
try {
ServerSocket ss = new ServerSocket(port);
System.out.println("server is running....");
while(true){
Socket s = ss.accept() ; //采用TcP协议
if(s!=null){
new RpcThread(s).start();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
RpcThread:
public class RpcThread extends Thread {
private Socket socket;
public RpcThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
ObjectInputStream is = null;
ObjectOutputStream os = null;
try {
//从TcP报文获取数据
is = new ObjectInputStream(socket.getInputStream());
// 得到远程调用参数,包含了接口名,调用方法,方法参数
RpcObject rpcObject = (RpcObject) is.readObject();
System.out.println("Method:"+rpcObject.getMethodName());
// 构建接口的实现类,然后通过反射调用方法
Object o = getObject(rpcObject.getUrl());
System.out.println("class:"+rpcObject.getUrl());
Object reO = executeMethod(o, rpcObject.getMethodName(), rpcObject.getArgs());
// 输出返回值
os = new ObjectOutputStream(socket.getOutputStream());
os.writeObject(reO);
os.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(is!=null){
is.close();
}
if(os!=null){
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 通过反射技术执行方法,并返回返回值
*/
private Object executeMethod(Object o, String methodName, Object[] args) {
Object objR = null;
Class<?>[] cs = new Class[args.length];
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
cs[i] = arg.getClass();
}
try {
//获取类的方法;
Method m = o.getClass().getMethod(methodName, cs);
//动态调用该方法
objR = m.invoke(o, args);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return objR;
}
/*
* 根据url得到实例
*/
private Object getObject(String url) {
Object object = null;
try {
Class clz=Class.forName(url);
object = clz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}catch(Exception e)
{
e.printStackTrace();
}
return object ;
}
}
客户端:
RpcProxy:
public class RpcProxy implements InvocationHandler,
Serializable{
private String ip;
private int port;
private String url;
private static final long serialVersionUID = 1L;
public RpcProxy(String ip, int port, String url) {
this.ip = ip;
this.port = port;
this.url = url;
}
/**
* 动态代理类,当调用接口方法的时候转为调用此方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args
)throws Throwable {
// 用作返回值
Object o = null;
// 通过socket调用远程服务
Socket s = new Socket(ip, port);
// 组装为一个保留了要调用的类,方法名及参数的对象,然后序列化之后传给远程
RpcObject rpcObject = new RpcObject(url, method.getName(), args);
ObjectOutputStream os = null;
ObjectInputStream is = null;
try{
//在socket输入流建立对象流
os = new ObjectOutputStream(s.getOutputStream());
os.writeObject(rpcObject);// 把对象序列化,发送到服务端;
os.flush();// 马上发送
// 从远程得到返回结果
//在socket输入流建立对象流
is = new ObjectInputStream(s.getInputStream());
o = is.readObject(); // 反序列化,获取结果
} catch (Exception e) {
e.printStackTrace();
} finally{
if(os!=null){
os.close();
}
if(is!=null){
is.close();
}
}
return o;
}
}
entities类:
RpcObject:
public class RpcObject implements Serializable{
private static final long serialVersionUID = 1L;
private String url;
private String methodName;
private Object[] args;
public RpcObject() {
}
public RpcObject(String c, String methodName, Object[] args) {
this.url = c;
this.methodName = methodName;
this.args = args;
}
public String getUrl() {
return url;
}
public void setClass4Name(String url) {
this.url = url;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
}
被远程调用的方法:
public class Hello {
public String sayHello(String name) {
return "hello->>>>>>:" + name;
}
}
Main方法:
public class App2 {
public static Object test(String ip,int port,String msg)
{
String url="com.gbs.util.Hello";
String methodName="sayHello";
Object args[]={
msg};
// 用作返回值
Object o = null;
// 通过socket调用远程服务
try{
Socket s = new Socket(ip, port);
// 组装为一个保留了要调用的类,方法名及参数的对象,然后序列化之后传给远程
RpcObject rpcObject = new RpcObject(url, methodName, args);
ObjectOutputStream os = null;
ObjectInputStream is = null;
try{
os = new ObjectOutputStream(s.getOutputStream());
os.writeObject(rpcObject);
os.flush();
// 从远程得到返回结果
is = new ObjectInputStream(s.getInputStream());
o = is.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}
catch(Exception e)
{
e.printStackTrace();
}
return o;
}
public static void main(String[] args) {
System.out.println(test("localhost",9001,"helloworld").toString());
}
}