前言
“一旦開始了就要堅持下去“。為什麼本文的第一句話是這麼一句話呢,因為我經常就是開頭轟轟烈烈,結果越來越枯燥,就不想做下去了。但是版圖就放棄又那麼不甘心,繼續加油吧。
吐槽完畢,進入正題。在上一篇中我們的主角LayIM已經登場了。而且介面已經實現,那麼有些小夥伴就有疑惑了,詳細流程是什麼樣的,今天我就介紹一個東西,那就是 /layim/init 介面的實現細節
另外,專案已經升級至 .NET CORE 2.1 ,最新程式碼在 dev-netcore2.1 分支上
需求
需求是什麼?需求是將LayIM的主介面顯示出來。如下:
嗯,就是這麼個東西。在上一篇中我已經介紹到,init介面就是為了實現主介面的,那麼主介面的資料是什麼樣的呢?(其實在兩年前的部落格中已經講過,這裡在稍微提一下)我們看一下DEMO中的getList.json.
如上圖,我們只要定義一個介面然後輸出上圖格式中的json資料即可。由於我在框架中用SQLServer給了一個預設實現,關係型資料庫那肯定是各種關係啦。首先定義最基本的表。
使用者表,使用者好友分組表,使用者好友關係表,群組表,群組群員關係表。目前這五個表足夠了。
下面逐個分析擊破:
mine:當前使用者資訊,從使用者表取出即可
friend:首先從使用者好友分組表取出當前使用者所有的分組,在從使用者好友關係表取出好友。然後程式中去匹配該好友對應的分組即可。及分組和好友是一對多的關係
group:從群組群員關係表中取出當前使用者所在的群,然後在從群組表取出相應的群資訊,組合資料即可
具體程式碼實現
下面的程式碼如果有不理解的地方,可以先從前面幾篇中補補課。
首先,毋庸置疑,先將路由配置上:
routes.AddQuery("/init", async context => await GetInitData(context));
GetInitData 做了什麼事呢?它就是獲取註冊的 ILayIMStorage 例項,然後呼叫介面方法獲取資料。
public interface ILayIMStorage { /// <summary> /// 初始化資料 /// </summary> /// <param name="userId"></param> /// <returns></returns> Task<LayIMInitModel> GetInitData(string userId); /// <summary> /// 儲存聊天記錄 /// </summary> /// <param name="message"></param> /// <returns></returns> Task<int> SaveMessage(LayIMMessageModel message); }
介面實現類
在專案 LayIM.AspNetCore.Storage.SqlServer中實現ILayIMStorage介面.Repository具體程式碼就不在貼上了,就是一系列Sql的查詢然後資料組合。
/// <summary> /// 獲取初始化資料 /// </summary> /// <param name="userId"></param> /// <returns></returns> public async Task<LayIMInitModel> GetInitData(string userId) { var mineTsk = userRepository.GetUserById(userId); var friendGroupsTask = friendGroupRepository.GetUserGroups(userId); var friendRelationsTask = friendRelationRepository.GetFriendRelations(userId); var groupIdsTask = groupMemberRepository.GetUserBigGroups(userId); LayIMInitModel initModel = new LayIMInitModel { //使用者自己 mine = await mineTsk }; //好友列表 List<FriendGroupModel> friend = new List<FriendGroupModel>(); IEnumerable<FriendGroupModel> friendGroups = await friendGroupsTask; IEnumerable<FriendRelationShip> friendRelations = await friendRelationsTask; IEnumerable<long> friendIds = friendRelations.Select(x => x.FriendId); IEnumerable<UserModel> friends = await userRepository.GetUsersByIds(friendIds); if (friendIds?.Count() > 0) { foreach (var group in friendGroups) { var friendIdsInGroup = friendRelations.Where(r => r.GroupId == group.id).Select(r => r.FriendId); group.list = friends.Where(x => friendIdsInGroup.Any(f => f == x.id)); } } friend.AddRange(friendGroups); initModel.friend = friend; //群組列表 IEnumerable<long> groupIds = await groupIdsTask; var bigGroupsTask = bigGroupRepository.GetBigGroups(groupIds); initModel.group = await bigGroupsTask; return initModel; }
寫完方法之後,記得要註冊服務。
/// <summary> /// 使用SqlServer /// </summary> /// <param name="services"></param> /// <param name="setConfig"></param> public static IServiceCollection AddSqlServer(this IServiceCollection services,string connectionString) { var dbConfig = new DBConnectionConfig(DBType.SqlServer) { ConnectionString = connectionString }; services.AddSingleton(dbConfig); services.AddSingleton<ILayIMStorage, LayIMDapperStorage>(); return services; }
然後在Demo中的使用方法如下:
services.AddLayIM().AddRongCloud(config => { config.AppKey = "appkey"; config.AppSecret = "appsecret"; }) .AddSqlServer("connectionString");
重啟專案,測試一下 layim/init 介面。資料返回正常
當然,一個好友的使用者資料一般變化不大,所以對於介面要增加快取設計。不過這裡我暫時沒有實現,只是先臨時用了 IMemoryCache。
請求回放
首先,由於請求的 Path 是 /layim 開頭的,所以中介軟體判定為LayIM請求,然後在經過路由轉發器,找到對應的處理器。
var dispatcher = LayIMRoutes.Routes.FindDispatcher(path);
之前已經介紹過,Dispatcher 是實現了Dispatch 方法的。
internal interface ILayIMDispatcher { Task Dispatch(HttpContext context); }
所以,最終的請求其實都會落到路由註冊的方法中,也就是上文中的 routes.AddQuery("/init", async context => await GetInitData(context)); 那麼其他的返回ContentType,轉JSON就是框架實現了,業務沒必要關心它了。
說到這裡可能大家還是比較迷糊,下面是一個Dispatcher之間的關係圖.
MethodFilterDispatcher 抽象類 負責請求方法的校驗。GET POST PUT DELETE 等
CommandDispatcher<TResult> 抽象類 負責主業務邏輯處理,模板方法,處理細節交給實現類
ExecuteCommandDispatcher<TResult> 實現類,POST請求
QueryCommandDispatcher<TResult> 實現類,GET 請求
其他待擴充套件
總結
本文通過一個 /layim/init 介面的詳細介紹,通過這個介面請求流程,大家能夠對框架的處理部分設計有所理解。另外,本文內容都是在後端,至於前臺怎麼繫結資料處理等,我們們下回分解。
部落格預告:LayIM.AspNetCore Middleware 開發日記(六)嵌入資源的使用,layim.config的封裝
專案地址:https://github.com/fanpan26/LayIM.AspNetCore 歡迎小夥伴們star 圍觀 提意見。