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. 什么是代 ...
随机推荐
- Mysql表的横向拆分与纵向拆分
表的拆分分为横向拆分(记录的拆分)和纵向拆分(字段的拆分).拆分表的目的:提高查询速度. 1.横向拆分 我们从一个案例去解释,情景是这样的:某某博客,有50W的博客量,有2w的用户,发现随着用户和博客 ...
- linux安装后需要进行的一些基本设置
修改网络: 在终端中输入:vi /etc/sysconfig/network-scripts/ifcfg-ens33 然后重启网络服务:systemctl restart network.servic ...
- linux - mysql:查看 mysql 是否安装成功
命令 rpm -q mysql 结果 成功: 失败:
- Oracle SQL的优化
SQL的优化应该从5个方面进行调整:1.去掉不必要的大型表的全表扫描2.缓存小型表的全表扫描3.检验优化索引的使用4.检验优化的连接技术5.尽可能减少执行计划的Cost SQL语句:是对数据库(数据) ...
- 阶段5 3.微服务项目【学成在线】_day04 页面静态化_13-页面静态化-数据模型-轮播图DataUrl接口
要开发轮播图的DataUrl的接口 轮播图的配置的集合 xc-framework-model这个module下 CmsConfigModel的类的属性 定义接口 在api里面定义接口:CmsConfi ...
- Qt编写自定义控件24-图片轮播控件
一.前言 上一篇文章写的广告轮播控件,采用的传统widget堆积设置样式表做的,这次必须要用到更高级的QPainter来绘制了,这个才是最高效的办法,本控件参考雨田哥的轮播控件,经过大规模的改造而成, ...
- swift 第十一课 结构体定义model类
结构体是可以作为 model 类使用的不过也要 写下的创建方法 import UIKit/***创建一个model 结构,重写init 方法,结构体的属性不能出现可选类型**/ struct Mode ...
- Shell中特殊字符的含义
$0 这个程式的执行名字 $n 这个程式的第n个参数值,n=1..9 $* 这个程式的所有参数,此选项参数可超过9个. $# 这个程式的参数个数 $$ 这个程式的PID(脚本运行的当前进程ID号) $ ...
- 使用webpack搭建一个多页应用
一.前言 最近需要为公司的活动写8个左右的移动端分享页面,有比较多的页面是公用的,如果用传统的方式来写的话,对于公用的代码抽取,css代码的压缩都是比较麻烦的,所以选择了webpack来搭建一个基本 ...
- [转载]由浅入深探究mysql索引结构原理、性能分析与优化
第一部分:基础知识第二部分:MYISAM和INNODB索引结构1. 简单介绍B-tree B+ tree树 2. MyisAM索引结构 3. Annode索引结构 4. MyisAM索引与InnoDB ...