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. 什么是代 ...
随机推荐
- ORM SQLAlchemy 表于表的关系
1表与表之间三种关系 1.1 一对一关系 举例: 一个丈夫对应一个妻子,一个妻子对应一个丈夫 1.2 一对多关系 举例:一个人可以拥有多辆汽车,要求查询某个人拥有的所有车辆 分析:这种情况其实也可以采 ...
- Golang的文件处理方式-常见的读写
在 Golang 语言中,文件使用指向 os.File 类型的指针来表示的,也叫做文件句柄.注意,标准输入 os.Stdin 和标准输出 os.Stdout ,他们的类型都是 *os.File 哟.在 ...
- springboot自定义异常RESTful返回异常
1.自定义异常类 package com.zhx.common.exception; import com.zhx.common.model.ErrorCode; /** * @Author: Sim ...
- tp5 回滚事务记录,其中一条语句报错,全部回滚
#################################### 测试事务 // 启动事务 Db::startTrans(); try { //插入行为表 $data = [ 'userId' ...
- 性能调优 | 如何通过性能调优突破 MySQL 数据库性能瓶颈?
本文出自头条号老王谈运维,转载请说明出处. MySQL 数据库瓶颈对 DBA 程序员而言,是非常棘手的问题.要正确的优化SQL,我们需要快速定位能性的瓶颈点,也就是说快速找到我们SQL主要的开销在哪里 ...
- Facebook币Libra学习-5.Move组织目录
Move是一种新的编程语言,旨在为Libra Blockchain提供安全可编程的基础. 组织 Move语言目录由五部分组成: 的虚拟机(VM),其中包含的字节码格式,字节码解释器,和基础设施执行事务 ...
- C++ STL Heap算法
#include <iostream>#include <algorithm>#include <vector> using namespace std; int ...
- cmake log
20:28:54: 为项目RoboticArmProject_CarTerminal_V20190530执行步骤 ...20:28:54: 正在启动 "/usr/bin/make" ...
- Ideal常用 快捷键
IntelliJ Idea 常用快捷键列表 Alt+回车 导入包,自动修正Ctrl+N 查找类Ctrl+Shift+N 查找文件Ctrl+Alt+L 格式化代码 Ctrl+Alt+O 优化导 ...
- CALL 'SYSTEM' ID 'COMMAND'
CALL 'SYSTEM' ID 'COMMAND' 语句创建 AL11文件夹 , line(), END OF tabl. DATA: lt_string TYPE STANDARD TABLE O ...