为了简便,所有代码写在一个包下,但不妨碍理解~~
package testRPC;
public class RPCClient {
public static void main(String[] args) {
sendMsg("aaa");
sendMsg("bbb");
sendMsg("ccc");
}
@Path(ipAndPort = "127.0.0.1:6060")
private static void sendMsg(String msg){
ServerService clientService = (ServerService) ClientServiceProxyFactory.getClientService(ServerService.class);
System.out.println("key:" + msg + ",value:" + clientService.get(msg));
}
}
package testRPC;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.util.Arrays;
public class ClientServiceProxyFactory {
public static Object getClientService(Class interfaceClazz) {
return Proxy.newProxyInstance(interfaceClazz.getClassLoader(), new Class[]{interfaceClazz},
(proxy, method, args) -> getRPCResulet(method,args));
}
/**
* 通过socket远程连接server调用服务端实现类,并返回结果
* @param method 代理的方法
* @param args 代理方法参数
* @return 远程调用返回结果
*/
private static Object getRPCResulet(Method method, Object[] args){
Object back = null;
String[] path = getPath();
//默认ip:127.0.0.1
String ip = "127.0.0.1";
//端口号默认设80
int port = 80;
if(null != path){
System.out.println((Arrays.asList(path)));
ip = path[0];
try {
port = Integer.parseInt(path[1]);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
ObjectOutputStream objOutStream = null;
Socket client;
try {
client = new Socket(ip,port);
objOutStream = new ObjectOutputStream(client.getOutputStream());
objOutStream.writeUTF(method.getName());
objOutStream.writeObject(method.getParameterTypes());
objOutStream.writeObject(args);
try (ObjectInputStream objInStream = new ObjectInputStream(client.getInputStream())) {
back = objInStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if(null != objOutStream)
objOutStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return back;
}
/**
* 根据客户端Path注解获取所发送的ip+端口信息
* @return ip+端口信息String[]
*/
private static String[] getPath(){
try {
Method method = RPCClient.class.getDeclaredMethod("sendMsg", String.class);
Path path = method.getDeclaredAnnotation(Path.class);
//为简化,假设ip和端口格式合法,暂不做格式校验
String ipAndPort = path.ipAndPort();
return ipAndPort.split(":");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}
package testRPC;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Path {
String ipAndPort() default "127.0.0.1:80";
}
package testRPC;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RPCServer {
private static ExecutorService pool = Executors.newCachedThreadPool();
public static void main(String[] args) {
//执行远程服务
runRPCServer(new ServerServiceImpl(),6060);
}
/**
* 执行远程服务
* @param service 服务端实现类
*/
private static void runRPCServer(Object service,int port){
ServerSocket server = null;
try {
server = new ServerSocket(port);
System.out.println("服务端口:" + port + "启动...");
while(true){
final Socket accept = server.accept();
System.out.println("收到请求");
pool.submit(new Runnable() {
public void run() {
ObjectInputStream input = null;
ObjectOutputStream output = null;
try {
// 从监听的socket中获得输入流
input = new ObjectInputStream(accept.getInputStream());
String methodName = input.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
//客户端代理中发送的代理方法的参数Object[]
Object[] args = (Object[]) input.readObject();
// 从监听的socket中获得输出流
output = new ObjectOutputStream(accept.getOutputStream());
Method method = service.getClass().getMethod(methodName, parameterTypes);
Object back = method.invoke(service, args);
output.writeObject(back);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(null != server){
server.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package testRPC;
public interface ServerService {
String get(Object key);
}
package testRPC;
import java.util.HashMap;
import java.util.Map;
public class ServerServiceImpl implements ServerService {
public String get(Object key) {
Map<String,Object> map = new HashMap<String, Object>();
map.put("aaa","111");
map.put("bbb","222");
map.put("ccc",new Object());
Object obj = map.get(key);
if(null == obj){
return null;
}
if(obj instanceof String){
return (String)obj;
}
return obj.toString();
}
}