基于动态代理的WebAPI/RPC/webSocket框架

Posted hubro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于动态代理的WebAPI/RPC/webSocket框架相关的知识,希望对你有一定的参考价值。

API/RPC/webSocket三个看起来好像没啥相同的地方,在开发时,服务端,客户端实现代码也大不一样

最近整理了一下,通过动态代理的形式,整合了这些开发,都通过统一的接口约束,服务端实现和客户端调用

 

先上RPC示例

服务端

接口和接口实现

public interface ITest
        {
            bool login(int? a);
            string Test1(string msg, out string error);
        }
        public class Test : AbsService, ITest
        {
            [LoginPoint]//登录切入点
            public bool login(int? a)
            {
                SaveSession("user","token");
                return true;
            }
       
            public string Test1(string msg, out string error)
            {
                var user = CurrentUserName;
                var tag = CurrentUserTag;
                error = "error";
           
                return msg;
            }
        }

 

上面是一个标准接口和接口实现,并继承了AbsService,

Login方法标注了LoginPoint特性,表示登录切入点,调用此接口时首先得调用此方法,方法内SaveSession存储登录状态

Test1方法内使用了CurrentUserName,以获取登录方法保存的Session

服务启动

var server = new ServerCreater().CreatetRPC(805);
            server.CheckSign();
            server.SetSessionManage(new SessionManage());
            server.Register<ITest, Test>();//服务端注册接口和接口的实现
            server.Start();

  

CreateRPC是一个扩展方法,引用CRL.RPC获取

SetSessionManage,自定义Session存储,默认是内存里

CheckSign 处理请求时,进行参数签名验证

客户端

客户端接口定义

    public interface ITest
    {
        bool login(int? a);
        string Test1(string msg,out string error);
    }

  

接口调用

 var clientConnect = new RPCClientConnect("127.0.0.1", 805);
            clientConnect.UseSign();
int? a=null;
            client.login(a);//先登录认证
string error = "";
                var str = client.Test1("aaa",out error);
                Console.WriteLine($"return:{str} out:{error}");

 

客户端先调用login方法进行登录,并记录服务端返回的token

Test1方法将token回传给服务器以验证登录状态

当调用了UseSign方法,就会对提交的参数进行签名,签名KEY为登录后服务端返回的TOKEN,服务端同样按此对签名进行比较 

 

特点:

  • 通过接口约束服务端和客户端调用,参数定义透明化,out也支持
  • 真正的方法远程调用,任意参数类型,个数
  • 集成登录认证逻辑,自定义登录认证过程,也可以自定义Session实现

技术实现:

  • Dynamitey实现接口类型代理
  • DotNetty实现TCP通讯
  • 对象二进制序列化

动态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");
clientConnect.UseSign();
            var service = clientConnect.GetClient<ITestService>();
var str = service.Login("user", "123");
            Console.WriteLine(str);
int? a = 1;
            service.SendData("data",a);

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", 8015);
            clientConnect.UseSign();
            clientConnect.SubscribeMessage<socketMsg>((obj) =>
            {
                Console.WriteLine("OnMessage:" + obj.ToJson());
            });
            clientConnect.StartPing();
            var service = clientConnect.GetClient<ITestService>();
            var str = service.Login("user", "123");
int? a = 1;
            service.SendData("data", a);

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框架的主要内容,如果未能解决你的问题,请参考以下文章

基于JDK的动态代理技术详解

Spring aop 基于JDK动态代理和CGLIB代理的原理以及为什么JDK代理需要基于接口

Spring aop 基于JDK动态代理和CGLIB代理的原理以及为什么JDK代理需要基于接口

实现一个基于动态代理的 AOP

SPRING03_AOP的概述动态代理cglib代理相关概念基于xml配置基于注解配置

基于 CGLIB 库的动态代理机制