Java通过Socket和动态代理实现简易RPC框架
本文转自Dubbo作者梁飞大神的CSDN(https://javatar.iteye.com/blog/1123915),代码简洁,五脏俱全.
1.首先实现RpcFramework,实现服务的暴露与引用功能.
package com.zxd.dubbo.learning.rpc.framework; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.ServerSocket;
import java.net.Socket; /**
* @Project DubboLearning
* @Package com.zxd.dubbo.learning.rpc.framework
* @Author:zouxiaodong
* @Description:
* @Date:Created in 14:32 2018/10/24.
*/
public class RpcFramework { /**
* @FileName RpcFramework.java
* @ClassName RpcFramework
* @MethodName export
* @Desc 暴露服务
* @author zouxiaodong
* @date 2018/10/24 15:06
* @Params [service 服务实现, port 服务端口]
* @return void
*/
public static void export(final Object service,int port) throws IOException {
if(service == null){
throw new IllegalArgumentException("service instance == null");
}
if(port < 0 || port > 65535){
throw new IllegalArgumentException("Invalid port " + port);
}
System.out.println("Export service :" + service.getClass().getName() + " on port " + port);
ServerSocket serverSocket = new ServerSocket(port);
while (true){
try {
final Socket socket = serverSocket.accept();
new Thread(new Runnable() {
@Override
public void run() {
ObjectInputStream input = null;
ObjectOutputStream output = null;
try {
input = new ObjectInputStream(socket.getInputStream());
String methodName = input.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
Object[] arguments = (Object[]) input.readObject();
output = new ObjectOutputStream(socket.getOutputStream());
Method method = service.getClass().getMethod(methodName,parameterTypes);
Object result = method.invoke(service,arguments);
output.writeObject(result);
} catch (Exception e) {
System.err.println("1."+e.getMessage());
}finally {
try {
if(output != null){
output.close();
}
if(input != null){
input.close();
}
if(socket != null){
socket.close();
}
} catch (IOException e) {
System.err.println("2."+e.getMessage());
}
}
}
}).start();
}catch (Exception e){ }
}
} /**
* @FileName RpcFramework.java
* @ClassName RpcFramework
* @MethodName refer
* @Desc 引用服务
* @author zouxiaodong
* @date 2018/10/24 15:32
* @Params [interfaceClass 接口类型, host 服务器主机名, port 服务器端口]
* @return T 远程服务
*/
public static <T> T refer(final Class<T> interfaceClass,final String host,final int port){
if(interfaceClass == null){
throw new IllegalArgumentException("Interface class == null");
}
if(!interfaceClass.isInterface()){
throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!");
}
if (host == null || host.length() == 0) {
throw new IllegalArgumentException("Host == null!");
}
if (port <= 0 || port > 65535) {
throw new IllegalArgumentException("Invalid port " + port);
}
System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);
return (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket socket = new Socket(host,port);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(args);
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
try {
Object result = input.readObject();
if(result instanceof Throwable){
throw (Throwable)result;
}
return result;
}finally {
input.close();
output.close();
socket.close();
}
}
});
}
}
2.编写接口HelloService.java与实现类HelloServiceImpl.java
package com.zxd.dubbo.learning.rpc.framework; /**
* @Project DubboLearning
* @Package com.zxd.dubbo.learning.rpc.framework.api
* @Author:zouxiaodong
* @Description:
* @Date:Created in 15:50 2018/10/24.
*/
public interface HelloService {
String hello(String name);
}
package com.zxd.dubbo.learning.rpc.framework; /**
* @Project DubboLearning
* @Package com.zxd.dubbo.learning.rpc.framework.impl
* @Author:zouxiaodong
* @Description:
* @Date:Created in 15:51 2018/10/24.
*/
public class HelloServiceImpl implements HelloService {
@Override
public String hello(String name) {
return "Hello "+name;
}
}
3.编写提供者(暴露服务)
package com.zxd.dubbo.learning.rpc.framework; import java.io.IOException; /**
* @Project DubboLearning
* @Package com.zxd.dubbo.learning.rpc.framework
* @Author:zouxiaodong
* @Description:
* @Date:Created in 15:54 2018/10/24.
*/
public class RpcProvider {
public static void main(String[] args) throws IOException {
HelloService helloService = new HelloServiceImpl();
RpcFramework.export(helloService,12345);
}
}
4.编写消费者(引用服务)
package com.zxd.dubbo.learning.rpc.framework; /**
* @Project DubboLearning
* @Package com.zxd.dubbo.learning.rpc.framework
* @Author:zouxiaodong
* @Description:
* @Date:Created in 15:55 2018/10/24.
*/
public class RpcConsumer {
public static void main(String[] args){
HelloService helloService = RpcFramework.refer(HelloService.class,"127.0.0.1",12345);
String result = helloService.hello("CoderZZ");
System.out.println(result);
}
}
Java通过Socket和动态代理实现简易RPC框架的更多相关文章
- Java Proxy和CGLIB动态代理原理
动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...
- java反射机制与动态代理
在学习HadoopRPC时.用到了函数调用.函数调用都是採用的java的反射机制和动态代理来实现的,所以如今回想下java的反射和动态代理的相关知识. 一.反射 JAVA反射机制定义: JAVA反射机 ...
- Java反射机制以及动态代理
Java反射机制以及动态代理 Java反射机制 含义与功能 Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类 ...
- 简易RPC框架-客户端限流配置
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- 自行实现一个简易RPC框架
10分钟写一个RPC框架 1.RpcFramework package com.alibaba.study.rpc.framework; import java.io.ObjectInputStrea ...
- 简易RPC框架-SPI
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- 简易RPC框架-心跳与重连机制
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- Java中的JDK动态代理
所谓代理,其实就是相当于一个中间人,当客户端需要服务端的服务时,不是客户直接去找服务,而是客户先去找代理,告诉代理需要什么服务,然后代理再去服务端找服务,最后将结果返回给客户. 在日常生活中,就拿买火 ...
- Java核心技术点之动态代理
本篇博文会从代理的概念出发,介绍Java中动态代理技术的使用,并进一步探索它的实现原理.由于个人水平有限,叙述中难免出现不清晰或是不准确的地方,希望大家可以指正,谢谢大家:) 一.概述 1. 什么是代 ...
随机推荐
- ZT:阿里合伙人发文:十年磨一剑,自研数据库终拿世界第一
按:真正做技术的,就该这样. 以下为全文转载 (观察者网讯) 10月24日,阿里巴巴合伙人.高德总裁刘振飞在阿里云开发者社区发文,回忆从2009年启动“去IOE”工程到2019年OceanBase拿下 ...
- SQL-W3School-高级:SQL RIGHT JOIN 关键字
ylbtech-SQL-W3School-高级:SQL RIGHT JOIN 关键字 1.返回顶部 1. SQL RIGHT JOIN 关键字 RIGHT JOIN 关键字会右表 (table_nam ...
- 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_19-CMS前端页面查询开发-页面原型-Table组件测试
页面填充内容.用一个表格来显示内容 3.1.2.1 Element-UI介绍 本项目使用Element-UI来构建界面,Element是一套为开发者.设计师和产品经理准备的基于 Vue 2.0 的桌面 ...
- 【转】【很全很新】C3P0 连接池和 DBUtils 配合事务使用总结
[转]https://blog.csdn.net/guozhaohui628/article/details/84793028 很久没用原生连接池,最近想写个小功能,结果发现很多地方不太懂,然后网上搜 ...
- 动手生成 Delphi xe DBTreeview
tProductType表结构如下 object FDConnection1: TFDConnection Params.Strings = ( 'Database=ClothingT ...
- 公司手机打卡app时间和百度时间差30秒解决
问题: 某天发现公司手机打卡app时间和百度时间差30秒解决 分析: nginx 192.168.0.23 外网 : 220.236.7.43 mysql主 192.168.0.2 ...
- ubuntu报错解决和注意事项
1.在容器中安装expect报错 [root@kube-node3 target]# docker exec -it 36563e55c42b sh$ sudo apt-get install exp ...
- 关于macOS上常用操作命令(持续更新)
1.mac上显示/隐藏Finder中的隐藏文件: 显示隐藏文件:在终端中输代码“defaults write com.apple.finder AppleShowAllFiles -boolean t ...
- windows7-tomcat配置
1.下载 2.解压缩 3.配置环境变量 (1)计算机属性--高级系统配置--高级--环境变量--系统变量--新建 (2)CATALINA_HOME 如:C:\apache-tomcat-7.0.73 ...
- 《剑指offer》Q01-12 (牛客10.11)
目录 T1 二维部分有序数组查找 ☆ T2 字符串字符不等长替换 - 从后往前 T3 返回链表的反序 vector T4 重建二叉树 T5 两个栈模拟队列 T6 旋转数组中的最小元素 - 二分或暴力 ...