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实现(一)的更多相关文章

  1. Java 简单的rpc 一

    一,简单rpc 是基于Java socket 编程 ServerSocket serverSocket = new ServerSocket(9999); System.out.println(&qu ...

  2. Java 简单的RPC 实现

    借用了网上某大神的例子.... 目录结构是这样的... RpcFramework 主要是两个方法.一个是暴露服务,一个为引用服务.暴露服务的主要作用是声明一个接口的实现类.可以通过socket 远程调 ...

  3. 分布式架构的基石.简单的 RPC 框架实现(JAVA)

    前言 RPC 的全称是 Remote Procedure Call,它是一种进程间通信方式.允许像调用本地服务一样调用远程服务. 学习来源:<分布式系统架构:原理与实践> - 李林锋 1. ...

  4. Java实现简单的RPC框架(美团面试)

    一.RPC简介 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议.它允许像调用本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用) ...

  5. Java使用Netty实现简单的RPC

    造一个轮子,实现RPC调用 在写了一个Netty实现通信的简单例子后,萌发了自己实现RPC调用的想法,于是就开始进行了Netty-Rpc的工作,实现了一个简单的RPC调用工程. 如果也有兴趣动手造轮子 ...

  6. 最简单的RPC框架实现

    通过java原生的序列化,Socket通信,动态代理和反射机制,实现一个简单的RPC框架,由三部分组成: 1.服务提供者,运行再服务端,负责提供服务接口定义和服务实现类 2.服务发布者,运行再RPC服 ...

  7. Java自带RPC实现,RMI框架入门

    Java自带RPC实现,RMI框架入门 首先RMI(Remote Method Invocation)是Java特有的一种RPC实现,它能够使部署在不同主机上的Java对象进行通信与方法调用,它是一种 ...

  8. 面试题思考:Java RMI与RPC,JMS的比较

    RPC:(Remote Procedure Call)  被设计为在应用程序间通信的平台中立的方式,它不理会操作系统之间以及语言之间的差异. 支持多语言 RMI:(Remote Method Invo ...

  9. 如何实现一个简单的RPC

    在如何给老婆解释什么是RPC中,我们讨论了RPC的实现思路. 那么这一次,就让我们通过代码来实现一个简单的RPC吧! RPC的实现原理 正如上一讲所说,RPC主要是为了解决的两个问题: 解决分布式系统 ...

随机推荐

  1. JavaScript调试小技巧

    1.‘debugger;’ 除了console.log,debugger就是另一个我很喜欢的快速调试的工具,将debugger加入代码之后,Chrome会自动在插入它的地方停止,很像C或者Java里面 ...

  2. Android sdcard文件读写操作

    这次演示以,安卓原生操作系统 Nexus_6手机进行操作: AndroidManifest.xml配置相关权限: <!-- 增加权限 --> <uses-permission and ...

  3. Spring Boot 应用系列 3 -- Spring Boot 2 整合MyBatis和Druid,多数据源

    本文演示多数据源(MySQL+SQL Server)的配置,并且我引入了分页插件pagehelper. 1. 项目结构 (1)db.properties存储数据源和连接池配置. (2)两个数据源的ma ...

  4. Javascript设计模式理论与实战:状态模式

    在软件开发中,很大部分时候就是操作数据,而不同数据下展示的结果我们将其抽象出来称为状态,我们平时开发时本质上就是对应用程序的各种状态进行切换并作出相应处理.状态模式就是一种适合多种状态场景下的设计模式 ...

  5. jquery.cookie.js 删除cookie

    简单交代一下背景:asp.net页面的上的切换登录按钮的点击事件实现cookie的删除. 但是好像没办法直接删除,通过网上提供的方法,可以使用jquery.cookie.js 来操作cookie的创建 ...

  6. vux Tabbar组件入门备忘大佬多指点

    一.Tabbar引入及使用 1.新创建vue文件 2.在vue文件中添加插件 <template> <div> <tabbar style="position: ...

  7. 自定义两个控件,一个是显示图标和文字的矩形,一个是带边框的label(但是不是label)

    记录遇到的两个坑 坑1. 一开始我继承button 来实现下面的控件1,后面发现button没有双击事件.就改成继承UserControl了.重新编译,导致设计时的控件文本全部被清空,因为UserCo ...

  8. 如何: 在 VS中的设计时刻主从表绑定控件到数据库

    这个示例展示了如何在 Visual Studio 2005 的设计时刻,把一个 data-aware 控件 (XtraGrid.XtraPivotGrid.XtraVerticalGrid 等) 绑定 ...

  9. sqlserver插入之字符串+数字

    declare @i int,@a varchar(10)set @i = 0set @a='hiro--'+LTRIM(@i)while @i < 500begin insert into h ...

  10. 关于在C++中调用R函数以及RCpp使用

    最近因为项目要用到,所以在想办法把R语言用到C++中. 网上查了看到有一个Rcpp的工具.所以在这里总结一下. 现在能想到的几种在C++中调用R语言的方法如下: 1. 使用Rcpp R高级编程技巧及R ...