UMC介紹
UMC的全名是UI Model Command
,意思是讓UI響應服務端的模塊指令,實現上就是設計了一套客戶端與服務端交互的文本協議,此協議能讓就是客戶端用標準請求服務端、服務端用標準JSON格式響應客戶端。客戶端分析出JSON端包含的事件,數據和UI組件,達到操控和繪製客戶端目的,現在服務端我們已經用java
和.net
實現了此標準協議(後期我們會實現其他計算機語言),現在java
後端工程師和.net
後端工程師只要用此架構開發,就能快速實現了原生Android和原生IOS端和H5端和小程序(嵌套H5,後期會用原生小程序實現),H5都已經開源,此協議用一套標準,統一實現PC和H5端,小程序端,安卓和蘋果端的界面實現和後臺邏輯。
這也意為做,一個統一的後臺就可以管理各個終端,用此實現的業務不但開發維護簡單,業務維護也更簡單,對公司而言,有後端工程師就有各IOS和Android的團隊班子,對於後端工程師更是賦能,現在他們能開發Android和IOS應用了,對於Android和IOS工程師,讓他們告別雜亂UI繪製和UI跳轉方式,進入終端的組件式開發,且只要對新組件實現就可以了,讓終端開發更簡單,對發佈來太太減少APP版本發佈次數,我也相信每個後臺工程師和Android和IOS工程師都願意掌握此技能。
UMC是在數據通信上是採用Http GET
方式請求,為什麼採用GET方式呢,客戶端與服務端做為非文件交互,整體來說交互所要的數據是相當少,GET
方式足可滿足我們應用需要,如果需要文件交互,則採用先把資源上傳到文件服務器,再來由UMC處理,這樣就簡單高效了,還不用佔用帶寬,又起服務器分流等做用,此設計為我分佈式和API高性能網關提供了前期基礎。
再來說交互路由吧,我們用GET
用QueryString
來交互傳參,我們保留jsonp
參數做跨域使用,還有_model
和_cmd
就是我們的Model
與Command
,再除去_
開頭的參數就是這次有效請求的參數,就這樣根據Model
和Command
帶著參數去路由,跑一遍,把再結果返回給客戶端,就這樣完成這次請求了,他的原理就是這樣回事。下面我用java
講解如何實現。
UMC的IWebFactory、WebFlow、WebActivity
請求路由路線是由model和cmd來確認,他對應的後臺路由類分別為IWebFactory
接口,WebFlow
基類、WebActivity
基類,其中由IWebFactory
來確認接收那此model
並返回接收WebFlow
類,再就WebFlow
類確認cmd
,由那個WebActivity
處理,整個處理路由就是這樣,下面我們就來講解此邏輯
IWebFactory
//IWebFactory
public class FlowFactory implements IWebFactory {
@Override
public void init(WebContext context) {
}
@Override
public WebFlow flowHandler(String mode) {
switch (mode) {
case "Account":
return new AccountFlow();
}
return WebFlow.Empty;
}
}
WebFlow
上例代碼展示,此IWebFactory
只接收Account
的model
,此模塊的cmd
路由由AccountFlow
處理,下面我們就查看AccountFlow
代碼
public class AccountFlow extends WebFlow {
@Override
public WebActivity firstActivity() {
switch (this.context().request().cmd()) {
case "Login":
return new AccountLoginActivity();
case "Register":
return new AccountRegisterActivity();
case "Forget":
return new AccountForgetActivity();
case "Password":
return new AccountPasswordActivity();
}
return WebActivity.Empty;
}
}
從上列代碼可以就看到AccountFlow
,可以路由指令Login
,Register
,Forget
,Password
,每個指令都有自己的WebActivity
,WebActivity
就是我們的業務實現了,處理業務業務方法在processActivity
,下面我就用AccountLoginActivity
來說明WebActivity
的處理方式
WebActivity
public class AccountLoginActivity extends WebActivity {
@Override
public void processActivity(WebRequest request, WebResponse response) {
WebMeta user = this.asyncDialog(d ->
{
UIFormDialog dialog = new UIFormDialog();
dialog.title("賬戶登錄");
dialog.addText("用戶名", "Username", "").put("placeholder", "手機/郵箱");
dialog.addPassword("用戶密碼", "Password", "");
dialog.submit("登錄", request, "User");//事件對話框
dialog.addUIIcon('\uf1c6', "忘記密碼").put("Model", request.model()).put("Command", "Forget");
dialog.addUIIcon('\uf234', "註冊新用戶").put("Model", request.model()).put("Command", "Register");
return dialog;
}, "Login");
String username = user.get("Username");
Membership userManager = WebADNuke.Security.Membership.Instance();
int times = userManager.Password(username, passwork, maxTimes);
switch (times) {
case 0:
Identity iden = userManager.Identity(username);
AccessToken.login(iden, AccessToken.token(), request.isApp() ? "App" : "Client", true);
this.context().send("User", true);
break;
case -2:
this.prompt("您的用戶已經鎖定,請過後登錄");
break;
case -1:
this.prompt("您的用戶不存在,請確定用戶名");
break;
default:
this.prompt(String.format("您的用戶和密碼不正確,您還有%d次機會", maxTimes - times));
break;
}
}
}
我這裡先說說processActivity
方法的兩個參數吧,request
,response
其中request
是請求的所有參數信息都這裡,包含客戶端環境,是不是APP中,是不是微信中,客戶的IP是多少,和QueryString
參數,但request
把QueryString
規整化了,當請求中有model
和cmd
的時間,QueryString
單值可以request.sendValue()
獲取,多值可以用request.sendValues()
得到;當請求無model
和cmd
的時,則會把請求把QueryString
規整化到了對話框中,以對話框的方式獲取交互的值;response
客戶端響應對象,他可以完成數據輸出或跳轉。一句話就是request
是獲取客戶端信息,response
是操作響應內容的;
從上面講解中,我們知道QueryString
會規整到request
請求參數中去,這裡講一講請求參數與箭頭函數的之間的關係。箭頭函數在什麼樣的情況下執行呢,只有在請求參數或會話中找到這對話框的參數值,則執行箭頭函數獲得一個對話框給並返回到客戶端;先聲明一個對話框,對話框分為單值對話框和表單對話框,先說單值對話框與請求參數對應的關係吧,每個請求的對話框都有一個asyncId
,也就是asyncDialog
傳入進去asyncId
,確認asyncId
是不是有值,先從會話參數中找,如果沒有,從對話框參數池中找,如何不存在對話框參數,檢測request.sendValue()
還沒有值,再用asyncId
作為key來檢測request.sendValues()
,如果都沒值的情況下,再去執行箭頭函數獲取對話框。這就是單值對話框獲取值的邏輯,下面我們再說說表單對話框獲取值的方式,第一步也是一樣從會話參數中找,沒有找到,再看對話框參數池是不是表單值,如果不是或沒有,再看request.sendValues()
是不是能與此次表單asyncId
對應,(他的對應關係架構會自行處理)如果不是或沒有,再去執行箭頭函數獲取表單對話框。這就是表單對話框獲取值的邏輯;整個對話框都是為了讓對話框的asyncId
配對QueryString
,這也說明只要做準備好WebActivity
所要的的參數,就能執行完processActivity
邏輯,中途就不會去執行箭頭函數。
在對話框中從獲取值的方式上,可分為兩種,會話對話框和事件對話框,會話對話框前端提交之後就關閉,事件對話框是根據服務端返回的事件,進行關閉或者刷新。在我們的UIGridDialog
和UIFormDialog
都支持這兩種模式
現在我們講解一下上面的AccountLoginActivity
的processActivity
,此processActivity
有登錄表單對話框,此對話框並啟用了事件對話框,看dialog.submit("登錄", request, "User")
這塊表示啟用了事件對話框模式,
說明這麼多,實事上是希望大家理解此模式,這也就UMC架構的業務處理層的核心思想,其他的解譯都是豐富這模式下的應用場景。
回頭我們再看看AccountLoginActivity
的processActivity
方法,可從代碼中可以看出,此Activity有繪出一個用戶登錄的UIFormDialog
,還關聯到忘記密碼和用戶註冊,這就是我們登錄功能的全部代碼,是不是簡單,掌握他就能開發出高性能的Andord,IOS和H5和小程序,因為他們的對應的客戶端都是用原生程序寫的,不是比其他任何內嵌引擎的都要快,對應後端工程師來說,掌握他不併跨出後端的知識體系。他用的是後端架構思維,驅動各前端應用,是不是掌握他是不是更有價值呢。