天天看點

UMC面向Serverless的全棧開發架構,用後端體系開發原生移動應用

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和小程式,因為他們的對應的用戶端都是用原生程式寫的,不是比其他任何内嵌引擎的都要快,對應後端工程師來說,掌握他不并跨出後端的知識體系。他用的是後端架構思維,驅動各前端應用,是不是掌握他是不是更有價值呢。