基于动态代理的WebAPI/RPC/webSocket框架,一套接口定义,多个通讯方式
API/RPC/webSocket三个看起来好像没啥相同的地方,在开发时,服务端,客户端实现代码也大不一样
最近整理了一下,通过动态代理的形式,整合了这些开发,都通过统一的接口约束,服务端实现和客户端调用
基于这样的形式,WebAPI/RPC/webSocket只需要定义一套接口,就能达到通用的效果
示例接口约束
public class TestObj
{
public string Name { get; set; }
}
public interface ITestService
{
void Login();
bool Test1(int a,int? b,out string error);
TestObj Test2(TestObj obj);
}
public class TestService : AbsService, ITestService
{
[LoginPoint]
public void Login()
{
SaveSession("hubro", "", "test");
} public bool Test1(int a, int? b, out string error)
{
var user = CurrentUserName;
var tag = CurrentUserTag; error = "out error";
Console.WriteLine(a);
Console.WriteLine(b);
return true;
} public TestObj Test2(TestObj obj)
{
Console.WriteLine(obj.ToJson());
return obj;
}
}
上面是一个标准接口和接口实现,并继承了AbsService,
Login方法标注了LoginPoint特性,表示登录切入点,调用此接口时首先得调用此方法,方法内SaveSession存储登录状态
Test1方法内使用了CurrentUserName,以获取登录方法保存的Session
特点:
- 通过接口约束服务端和客户端调用,参数定义透明化,out也支持
- 真正的方法远程调用,任意参数类型,个数
- 集成登录认证逻辑,自定义登录认证过程,也可以自定义Session实现
- 集成简单数据签名,不用费心数据安全问题
技术实现:
- Dynamitey实现接口类型代理
- DotNetty实现TCP通讯
- 对象二进制序列化
RPC调用
服务端
var server = new ServerCreater().CreatetRPC();
server.CheckSign();
server.SetSessionManage(new SessionManage());
server.Register<ITestService, TestService>();
server.Start();
CreateRPC是一个扩展方法,引用CRL.RPC获取
SetSessionManage,自定义Session存储,默认是内存里
CheckSign 处理请求时,进行参数签名验证
客户端接口调用
var clientConnect = new RPCClientConnect("127.0.0.1", 805);
clientConnect.UseSign();
var service = clientConnect.GetClient<ITestService>();
label1:
service.Login();
Console.WriteLine("loginOk");
int? a = 1;
string error;
service.Test1(1, a, out error);
Console.WriteLine("error:" + error);
var obj2 = service.Test2(new TestObj() { Name = "test" });
Console.WriteLine("obj2:" + obj2.ToJson());
Console.ReadLine();
goto label1;
客户端先调用login方法进行登录,并记录服务端返回的token
Test1方法将token回传给服务器以验证登录状态,并进行远程调用
当调用了UseSign方法,就会对提交的参数进行签名,签名KEY为登录后服务端返回的TOKEN,服务端同样按此对签名进行比较
动态webApi
同样基于上文结构,接口定义就不粘贴了
服务端定义
var server = new ServerCreater().CreatetApi();
server.CheckSign();
server.SetSessionManage(new SessionManage());
server.Register<ITestService, TestService>();
var listener = new ServerListener();
//listener.Start("http://localhost:809/");//自定义监听
如果宿主是.NET网站 在web.config增加处理module
<system.webServer>
<modules>
<add name="DynamicModule" type="CRL.DynamicWebApi.DynamicModule" />
</modules>
</system.webServer>
如果是单独程序,启动ServerListener即可
客户端调用
var clientConnect = new CRL.DynamicWebApi.ApiClientConnect("http://localhost:53065");
//var clientConnect = new CRL.DynamicWebApi.ApiClientConnect("http://localhost:8022");
clientConnect.UseSign();
var service = clientConnect.GetClient<ITestService>();
label1:
service.Login();
Console.WriteLine("loginOk");
int? a = ;
string error;
service.Test1(, a, out error);
Console.WriteLine("error:" + error);
var obj2 = service.Test2(new TestObj() { Name = "test" });
Console.WriteLine("obj2:" + obj2.ToJson());
Console.ReadLine();
goto label1;
WebSocket
WebSocket是一个比较特殊的方式,常用来做双工通讯的方式,客户端能往服务端发送数,服务端也能往客户端发送据
除去服务端往客户端发数据,也可以采用接口调用的形式实现,在这里,服务端往客户端发送数据,客户端采用了订阅的方式
服务端实现
var server = new ServerCreater().CreatetWebSocket(8015);
server.CheckSign();
server.SetSessionManage(new SessionManage());
server.Register<ITestService, TestService>();
server.Start();
new CRL.Core.ThreadWork().Start("send", () =>
{
var socket = server.GetServer() as CRL.WebSocket.WebSocketServer;
socket.SendMessage("hubro", new socketMsg() { name = DateTime.Now.ToString() }, out string error);
Console.WriteLine("send msg");
return true;
}, 10);
上面演示代码,服务端开启了一个线程,定时往客户端"hubro"发送数据 socket.SendMessage
客户端实现
var clientConnect = new CRL.WebSocket.WebSocketClientConnect("127.0.0.1", );
clientConnect.UseSign();
clientConnect.SubscribeMessage<socketMsg>((obj) =>
{
Console.WriteLine("OnMessage:" + obj.ToJson());
});
clientConnect.StartPing();
var service = clientConnect.GetClient<ITestService>();
label1:
service.Login();
Console.WriteLine("loginOk");
int? a = ;
string error;
service.Test1(, a, out error);
Console.WriteLine("error:" + error);
var obj2 = service.Test2(new TestObj() { Name = "test" });
Console.WriteLine("obj2:" + obj2.ToJson());
Console.ReadLine();
goto label1;
clientConnect.SubscribeMessage就是订阅消息了,通过订阅的方式,处理服务端发送的数据
可以看到以上各种形式,服务端实现和客户端调用基本相同,定义的接口能重复使用,做接口通讯效果杠杠的
具体实现方式和细节功能参见源码和demo,已经开源,请自行下载
源码地址:
CRL:
https://github.com/hubro-xx/CRL5
RCP:
https://github.com/hubro-xx/CRL5/tree/master/RPC
WebAPI:
https://github.com/hubro-xx/CRL5/tree/master/DynamicWebApi
WebSocket:
https://github.com/hubro-xx/CRL5/tree/master/WebSocket
基于动态代理的WebAPI/RPC/webSocket框架,一套接口定义,多个通讯方式的更多相关文章
- .NET 下基于动态代理的 AOP 框架实现揭秘
.NET 下基于动态代理的 AOP 框架实现揭秘 Intro 之前基于 Roslyn 实现了一个简单的条件解析引擎,想了解的可以看这篇文章 https://www.cnblogs.com/weihan ...
- 实现一个简单的基于动态代理的 AOP
实现一个简单的基于动态代理的 AOP Intro 上次看基于动态代理的 AOP 框架实现,立了一个 Flag, 自己写一个简单的 AOP 实现示例,今天过来填坑了 目前的实现是基于 Emit 来做的, ...
- 动态代理到基于动态代理的AOP
动态代理,是java支持的一种程序设计方法. 动态代理实现中有两个重要的接口和类,分别是InvocationHandler(interface),Proxy(class). 要实现动态代理,必须要定义 ...
- mybatis源码学习:基于动态代理实现查询全过程
前文传送门: mybatis源码学习:从SqlSessionFactory到代理对象的生成 mybatis源码学习:一级缓存和二级缓存分析 下面这条语句,将会调用代理对象的方法,并执行查询过程,我们一 ...
- MyBatis学习(三)MyBatis基于动态代理方式的增删改查
1.前言 上一期讲到MyBatis-Statement版本的增删改查.可以发现.这种代码写下来冗余的地方特别多.写一套没啥.如果涉及到多表多查询的时候就容易出现问题.故.官方推荐了一种方法.即MyBa ...
- Java通过Socket和动态代理实现简易RPC框架
本文转自Dubbo作者梁飞大神的CSDN(https://javatar.iteye.com/blog/1123915),代码简洁,五脏俱全. 1.首先实现RpcFramework,实现服务的暴露与引 ...
- JDK动态代理在RPC框架中的应用
RPC框架中一般都有3个角色:服务提供者.服务消费者和注册中心.服务提供者将服务注册到注册中心,服务消费者从注册中心拉取服务的地址,并根据服务地址向服务提供者发起RPC调用.动态代理在这个RPC调用的 ...
- 带你手写基于 Spring 的可插拔式 RPC 框架(一)介绍
概述 首先这篇文章是要带大家来实现一个框架,听到框架大家可能会觉得非常高大上,其实这和我们平时写业务员代码没什么区别,但是框架是要给别人使用的,所以我们要换位思考,怎么才能让别人用着舒服,怎么样才能让 ...
- Java动态代理——框架中的应用场景和基本原理
前言 之前已经用了5篇文章完整解释了java动态代理的原理,本文将会为这个系列补上最后一块拼图,展示java动态代理的使用方式和应用场景 主要分为以下4个部分 1.为什么要使用java动态代理 2.如 ...
随机推荐
- hdu6312 2018杭电多校第二场 1004 D Game 博弈
Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 【Swagger】可能是目前最好的 Spring Boot 集成 swagger 的方案
[Swagger]可能是目前最好的Spring Boot集成 swagger 的方案 学习笔记:五
5 推导数据:处理数据.格式.编码.解码.排序 处理数据:从Head First Python 上下载资源文件,即:james.txt,julie.txt,mikey.txt,sarah.txt. 实 ...
- FreeSql (二十九)Lambda 表达式
FreeSql 支持功能丰富的表达式函数解析,方便程序员在不了解数据库函数的情况下编写代码.这是 FreeSql 非常特色的功能之一,深入细化函数解析尽量做到满意,所支持的类型基本都可以使用对应的表达 ...
- .Net基础篇_学习笔记_第四天_switch-case
swith-case 用来处理多条件的定值的判断. 语法: switch(变量或者表达式的值) { case 值1:要执行的代码: break: case 值2:要执行的代码: break: case ...
- C#中读写Xml配置文件常用方法工具类
场景 有时需要使用配置文件保存一些配置的属性,使其在下次打开时设置仍然生效. 这里以对xml配置文件的读写为例. 1.读取XML配置文. 2.写入XML配置文件. 3.匹配 XPath 表达式的第一个 ...
- map转java对象
pom依赖: <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons ...