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. eclipse中java build path下 allow output folders for source folders 无法勾选,该如何解决 eclipse中java build path下 allow output folders for source folders 无法勾选,

    在创建maven工程时,在设置output folders时,总是勾选以后,老是自动恢复到原来的状态,对比其他的maven的工程发现是在创建maven时候选择的项目为pom,而不是war或者jar,将 ...

  2. WPF画辐射图

    public void WriteLineCircle(double originX, double originY, double r, int lineCount,List<string&g ...

  3. String-680. Valid Palindrome II

    Given a non-empty string s, you may delete at most one character. Judge whether you can make it a pa ...

  4. (6)Oracle基础--简单查询

    .基本查询语句  SELECT [DISTINCT] column_name1,... | * FROM table_name [WHERE conditions]; P: DISTINCT关键字的作 ...

  5. day 49 数据分析, 数据聚合 F 查询 Q 查询

    6.聚合查询和分组查询 1.聚合查询aggregate 我们先通过一个例子来感受一下吧. 1 2 3 # 计算所有图书的平均价格 books = models.Book.objects.aggrega ...

  6. eclispe中使用python库 pyswip 进行prolog编程

    from pyswip import Prolog prolog = Prolog() prolog.assertz("father(michael,john)") prolog. ...

  7. template.js插件和ajax一起使用的例子

    template.js 一款 JavaScript 模板引擎,简单,好用.提供一套模板语法,用户可以写一个模板区块,每次根据传入的数据,生成对应数据产生的HTML片段,渲染不同的效果. https:/ ...

  8. 剑指offer四十九之把字符串转换成整数

    一.题目 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 二.思路 详见代码. 三.代码 public class Solution { ...

  9. 剑指offer二十四之二叉树中和为某一值的路径

    一.题目 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 二.思路 详见代码 三.代码 1.解答代码 im ...

  10. (转)LINUX CENTOS7下安装PYTHON

    LINUX CENTOS7下安装PYTHON 原文:http://www.cnblogs.com/lclq/p/5620196.html Posted on 2016-06-27 14:58 南宫羽香 ...