Java简单的RPC实现(一)
RPC使用java最基本的,传输层使用Socket,序列化使用Serializable,java 动态代理模式,但是未实现消息注册等相关信息
大道至简

server端
package com.rpc.entity;
import java.io.Serializable;
public class RpcObject implements Serializable{
private static final long serialVersionUID = 1L;
private Class<?> c;
private String methodName;
private Object[] args;
public RpcObject() {
}
public RpcObject(Class<?> c, String methodName, Object[] args) {
this.c = c;
this.methodName = methodName;
this.args = args;
}
public Class<?> getC() {
return c;
}
public void setC(Class<?> c) {
this.c = c;
}
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;
}
}
ConfMonitor
package com.rpc.server; import java.util.HashMap;
import java.util.Map; import com.rpc.service.impl.HelloImpl; /**
* 模拟配置,实际的框架中大部分都是使用xml进行配置的,比如Hessian是配置在web.xml的servlet属性里的
* @author cdwangzijian
*
*/
public class ConfMonitor {
@SuppressWarnings("rawtypes")
public static Map<String, Class> conf = new HashMap<String, Class>(); static {
conf.put("com.rpc.service.IHello", HelloImpl.class);
}
}
RpcThread
package com.rpc.server; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket; import com.rpc.entity.RpcObject; public class RpcThread extends Thread { private Socket s; public RpcThread(Socket s) {
this.s = s;
} @Override
public void run() { ObjectInputStream is = null;
ObjectOutputStream os = null; try { is = new ObjectInputStream(s.getInputStream()); // 得到远程调用参数,包含了接口名,调用方法,方法参数
RpcObject rpcObject = (RpcObject) is.readObject(); System.out.println("Method:"+rpcObject.getMethodName()); // 构建接口的实现类,然后通过反射调用方法
Object o = getObject(rpcObject.getC());
System.out.println("class:"+rpcObject.getC()); Object reO = executeMethod(o, rpcObject.getMethodName(), rpcObject.getArgs()); // 输出返回值
os = new ObjectOutputStream(s.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();
}
}
} /**
* 通过反射技术执行方法,并返回返回值
* @param o
* @param methodName
* @param args
* @return
*/
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;
} /**
* 根据接口名得到实例
* @param c
* @return
*/
private Object getObject(Class<?> c) {
Object o = null;
try { System.out.println("c.getName:"+c.getName()); o = ConfMonitor.conf.get(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return o;
}
}
StartUp
package com.rpc.server; import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket; /**
* RPC服务器启动
* @author cdwangzijian
*
*/
public class StartUp { public static final int port = 9001; public static void main(String[] args) {
exportRpc();
} /**
* 导出RPC接口
*/
private static void exportRpc() {
try {
ServerSocket ss = new ServerSocket(port);
while(true){
Socket s = ss.accept();
if(s!=null){
new RpcThread(s).start();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
HelloImpl
package com.rpc.service.impl;
import com.rpc.service.IHello;
public class HelloImpl implements IHello {
@Override
public String sayHello(String name) {
return "hello:" + name;
}
}
IHello
package com.rpc.service;
public interface IHello {
String sayHello(String name);
}
客户端实现:
ProxyFactory
package com.zhy.proxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; public class ProxyFactory { @SuppressWarnings("unchecked")
public static <T> T create(Class<T> c, String ip, int port) { InvocationHandler handler = new RpcProxy(ip, port, c); return (T) Proxy.newProxyInstance(c.getClassLoader(),new Class[] {c},handler);
}
}
RpcProxy
package com.zhy.proxy; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.Socket; import com.rpc.entity.RpcObject; /**
* 客户端接口代理
* 当客户端接口方法被调用的时候,把方法名,方法参数作为参数。
* 传送给远程服务执行,然后获取返回值
* @author cdwangzijian
*
*/
public class RpcProxy implements InvocationHandler, Serializable{ private String ip;
private int port;
private Class<?> c; private static final long serialVersionUID = 1L; public RpcProxy(String ip, int port, Class<?> c) {
this.ip = ip;
this.port = port;
this.c = c;
} /**
* 动态代理类,当调用接口方法的时候转为调用此方法
*/
@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(c, method.getName(), 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(); } finally{ if(os!=null){
os.close();
} if(is!=null){
is.close();
} } return o;
} }
RpcClient
package com.zhy; import com.rpc.service.IHello;
import com.zhy.proxy.ProxyFactory; public class RpcClient {
public static void main(String[] args) { String ip = "localhost";
int port = 9001; IHello hello = ProxyFactory.create(IHello.class, ip, port); System.out.println(hello.sayHello("小明")); }
}
输出结果:

Java简单的RPC实现(一)的更多相关文章
- Java 简单的rpc 一
一,简单rpc 是基于Java socket 编程 ServerSocket serverSocket = new ServerSocket(9999); System.out.println(&qu ...
- Java 简单的RPC 实现
借用了网上某大神的例子.... 目录结构是这样的... RpcFramework 主要是两个方法.一个是暴露服务,一个为引用服务.暴露服务的主要作用是声明一个接口的实现类.可以通过socket 远程调 ...
- 分布式架构的基石.简单的 RPC 框架实现(JAVA)
前言 RPC 的全称是 Remote Procedure Call,它是一种进程间通信方式.允许像调用本地服务一样调用远程服务. 学习来源:<分布式系统架构:原理与实践> - 李林锋 1. ...
- Java实现简单的RPC框架(美团面试)
一.RPC简介 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议.它允许像调用本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用) ...
- Java使用Netty实现简单的RPC
造一个轮子,实现RPC调用 在写了一个Netty实现通信的简单例子后,萌发了自己实现RPC调用的想法,于是就开始进行了Netty-Rpc的工作,实现了一个简单的RPC调用工程. 如果也有兴趣动手造轮子 ...
- 最简单的RPC框架实现
通过java原生的序列化,Socket通信,动态代理和反射机制,实现一个简单的RPC框架,由三部分组成: 1.服务提供者,运行再服务端,负责提供服务接口定义和服务实现类 2.服务发布者,运行再RPC服 ...
- Java自带RPC实现,RMI框架入门
Java自带RPC实现,RMI框架入门 首先RMI(Remote Method Invocation)是Java特有的一种RPC实现,它能够使部署在不同主机上的Java对象进行通信与方法调用,它是一种 ...
- 面试题思考:Java RMI与RPC,JMS的比较
RPC:(Remote Procedure Call) 被设计为在应用程序间通信的平台中立的方式,它不理会操作系统之间以及语言之间的差异. 支持多语言 RMI:(Remote Method Invo ...
- 如何实现一个简单的RPC
在如何给老婆解释什么是RPC中,我们讨论了RPC的实现思路. 那么这一次,就让我们通过代码来实现一个简单的RPC吧! RPC的实现原理 正如上一讲所说,RPC主要是为了解决的两个问题: 解决分布式系统 ...
随机推荐
- 序列化Json时遇到的大小写问题及解决方法
最近在一个webapi2项目中遇到了一个问题:C#编码规范中规定属性的首字母是大写的(大多数公司采用这种编码风格),但是从其它系统中接收到的json对象的属性却是小写的(大多数公司采用这种编码风格), ...
- SQL Server Extended Events 进阶 1:从SQL Trace 到Extended Events
http://www.sqlservercentral.com/articles/Stairway+Series/134869/ SQL server 2008 中引入了Extended Events ...
- VS2012 中不能安装ARCGIS 10.0 SDK的解决方法
问题描述 在ARCGIS 安装SDK时 就会出错 原因是ARCGIS SDK 10.0只能在VS2010中安装,因为我本机是安的VS2012所以安装不成功. 解决方法 一,在注册表中HKE ...
- MongoDB Windowns 配置使用
MongoDB 下载 MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB 预编译二进制包下载地址:https://www.mo ...
- JWT+Log4net配置与使用
Log4net的优点 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.程序运行过 ...
- Disruptor使用简介
disruptor是lmax公司开发的一款java高性能并发框架,其本质是一种类似队列的实现“生产者—消费者 ”模式的组件. 下面是其示例代码: public class DisruptorServe ...
- python 返回数组的索引
使用python里的index nums = [1, 2, 3, 4, 5, 6, 1, 9] print nums.index(max(nums)) print nums.index(1) 该方法同 ...
- for循环、for in整理
for循环 作用:按照一定的规律,重复去做某件事情,此时我们就需要使用循环来处理了 例子1:倒着输出每一项 <script type="text/javascript"> ...
- 关于使用Iscroll.js异步加载数据后不能滑动到最底端的问题解决方案
关于使用Iscroll.js异步加载数据后不能滑动到最底端,拉到最下边又弹回去的问题困扰了我老半天,相信很多朋友都遇到了.我刚好不小心解决了,和大家分享一下.由于各种忙,下边就直接上代码吧. (前提是 ...
- python3 内置函数详解
内置函数详解 abs(x) 返回数字的绝对值,参数可以是整数或浮点数,如果参数是复数,则返回其大小. # 如果参数是复数,则返回其大小. >>> abs(-25) 25 >&g ...