国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

一種基于指令驅(qū)動(dòng)模型的移動(dòng)編程通訊接口的設(shè)計(jì)與實(shí)現(xiàn)

2020-09-02 06:52:20王樂琪
關(guān)鍵詞:網(wǎng)絡(luò)接口發(fā)送器接收器

侯 杰,王 靜,2,王樂琪

1(上海海洋大學(xué) 信息學(xué)院,上海 201306)2(農(nóng)村農(nóng)業(yè)部漁業(yè)信息重點(diǎn)實(shí)驗(yàn)室,上海 201306)

E-mail:wangjing@shou.edu.cn

1 引 言

隨著智能手機(jī)、平板電腦等移動(dòng)設(shè)備的普及,各類移動(dòng)應(yīng)用的發(fā)展愈加繁榮[1].與此同時(shí),移動(dòng)應(yīng)用的體積越來越龐大,通過網(wǎng)絡(luò)接口獲取數(shù)據(jù)是移動(dòng)應(yīng)用展示內(nèi)容的主要來源[2,3],因此移動(dòng)應(yīng)用中的網(wǎng)絡(luò)通訊模塊也變得越來越重要.由于移動(dòng)應(yīng)用與網(wǎng)絡(luò)接口的交互在移動(dòng)應(yīng)用開發(fā)中具有重要地位,并且在移動(dòng)應(yīng)用程序中,網(wǎng)絡(luò)接口請(qǐng)求的代碼塊非常多而且所在位置比較離散,所以移動(dòng)應(yīng)用和網(wǎng)絡(luò)接口的交互模塊在編寫和調(diào)試上具有較高的復(fù)雜度,影響著移動(dòng)應(yīng)用的開發(fā)效率.

目前存在很多成熟的框架可用于實(shí)現(xiàn)移動(dòng)應(yīng)用與網(wǎng)絡(luò)接口交互的開發(fā),例如在安卓開發(fā)中可以采用Retrofit請(qǐng)求框架,后臺(tái)則常采用Struts2,SpringMVC等框架[4,5].這些框架對(duì)于移動(dòng)開發(fā)中的網(wǎng)絡(luò)通訊模塊已經(jīng)給出了可行的解決方案.在后臺(tái)服務(wù)器編寫接口,移動(dòng)應(yīng)用程序中編寫請(qǐng)求.對(duì)于每一個(gè)移動(dòng)端的網(wǎng)絡(luò)接口調(diào)用,在服務(wù)器端對(duì)應(yīng)已編寫好的url,實(shí)現(xiàn)對(duì)應(yīng)請(qǐng)求參數(shù)的處理代碼模塊.這種明確的分工使得移動(dòng)應(yīng)用開發(fā)中的接口調(diào)試與協(xié)同開發(fā)變得困難和復(fù)雜.在沒有開發(fā)網(wǎng)絡(luò)接口之前,移動(dòng)端開發(fā)時(shí)的UI顯示只能使用假數(shù)據(jù)填充,之后再改為網(wǎng)絡(luò)接口請(qǐng)求來的數(shù)據(jù),并調(diào)試接口數(shù)據(jù)的適配問題,其中開發(fā)出錯(cuò)率,以及開發(fā)復(fù)雜度都顯著提高.問題在于服務(wù)器端和移動(dòng)端在開發(fā)模塊實(shí)現(xiàn)隔離的同時(shí)對(duì)交互數(shù)據(jù)也進(jìn)行了隔離,因而難以實(shí)現(xiàn)協(xié)同開發(fā).因而,涉及網(wǎng)絡(luò)請(qǐng)求的移動(dòng)應(yīng)用開發(fā)不能僅考慮移動(dòng)端,如何讓移動(dòng)端和服務(wù)器端相輔相成,配合恰當(dāng),在簡化移動(dòng)端的同時(shí)可以讓服務(wù)器端也方便的開發(fā)接口,實(shí)現(xiàn)協(xié)同開發(fā),從而降低開發(fā)復(fù)雜度,讓移動(dòng)端和服務(wù)器端具有數(shù)據(jù)一致性的同時(shí)也具有模塊隔離性,是目前移動(dòng)應(yīng)用中網(wǎng)絡(luò)通訊模塊設(shè)計(jì)與開發(fā)面臨的主要問題.

本文采用面向?qū)ο笏枷雽?duì)移動(dòng)編程通訊接口設(shè)計(jì),在服務(wù)器端引入指令驅(qū)動(dòng)模型,通過JSON格式的請(qǐng)求指令實(shí)現(xiàn)請(qǐng)求數(shù)據(jù)和返回?cái)?shù)據(jù)端到端的處理,使移動(dòng)端與服務(wù)器端具備數(shù)據(jù)一致性,從而提高移動(dòng)端與服務(wù)器端的協(xié)同開發(fā)效率,并且提高了應(yīng)用程序的可擴(kuò)展性和測(cè)試效率.進(jìn)一步基于此架構(gòu),以Android 應(yīng)用為例介紹具體開發(fā)過程和效果.

2 基于指令驅(qū)動(dòng)模型的移動(dòng)應(yīng)用通訊接口設(shè)計(jì)

2.1 通用開發(fā)模式

移動(dòng)應(yīng)用網(wǎng)絡(luò)接口開發(fā)是典型的前后端分離式的開發(fā),移動(dòng)應(yīng)用想要訪問服務(wù)器資源,需要通過HTTP協(xié)議向指定的服務(wù)器傳遞信息,服務(wù)器根據(jù)應(yīng)用請(qǐng)求調(diào)用相應(yīng)的接口,并返回相應(yīng)的結(jié)果.整個(gè)流程所涉及的操作為移動(dòng)端定義請(qǐng)求接口方法,創(chuàng)造請(qǐng)求數(shù)據(jù),填充URL和數(shù)據(jù),向服務(wù)器發(fā)送請(qǐng)求,服務(wù)器調(diào)用指定URL的網(wǎng)絡(luò)接口處理請(qǐng)求,返回請(qǐng)求結(jié)果,移動(dòng)端根據(jù)請(qǐng)求結(jié)果刷新UI.移動(dòng)應(yīng)用網(wǎng)絡(luò)接口的通用設(shè)計(jì)模式如圖1所示.

圖1 通用設(shè)計(jì)示意圖Fig.1 General design diagram

在這種設(shè)計(jì)模式下,移動(dòng)端與服務(wù)器端交互時(shí)傳遞的數(shù)據(jù)較為復(fù)雜,并且特定URL的請(qǐng)求數(shù)據(jù)和返回?cái)?shù)據(jù)必須事先約定.然而,請(qǐng)求數(shù)據(jù)和URL之間卻沒有明確的聯(lián)系,如果在發(fā)送請(qǐng)求時(shí)攜帶了錯(cuò)誤的請(qǐng)求數(shù)據(jù),移動(dòng)端將不能接受到正常的返回結(jié)果.本模式中存在的另一個(gè)問題是接口對(duì)請(qǐng)求數(shù)據(jù)的邏輯處理耦合在接口之中,即使是使用MVC架構(gòu)將邏輯處理模塊獨(dú)立起來,邏輯處理模塊所處理的數(shù)據(jù)仍然需要通過上層數(shù)據(jù)接收層傳遞給它,并沒有把網(wǎng)絡(luò)請(qǐng)求的發(fā)送與接收完全屏蔽,無法真正實(shí)現(xiàn)移動(dòng)端像調(diào)用函數(shù)一樣調(diào)用接口,無法達(dá)到移動(dòng)端與服務(wù)器端數(shù)據(jù)的一致性.因而,本文提出基于指令驅(qū)動(dòng)模型對(duì)移動(dòng)應(yīng)用通訊接口的整個(gè)架構(gòu)進(jìn)行優(yōu)化,確保請(qǐng)求數(shù)據(jù)與URL之間具有明確的聯(lián)系,而且能夠?qū)崿F(xiàn)數(shù)據(jù)傳輸與數(shù)據(jù)處理的隔離.

2.2 框架整體設(shè)計(jì)

本文提出的編程架構(gòu)共分為四個(gè)模塊,構(gòu)造請(qǐng)求指令,指令發(fā)送器,指令接收器,指令驅(qū)動(dòng)模型,其中構(gòu)造請(qǐng)求指令和指令驅(qū)動(dòng)模型是一組,指令發(fā)送器和指令接收器是一組.整個(gè)流程如圖2所示.

圖2 整體架構(gòu)設(shè)計(jì)Fig.2 Overall architecture design

圖2中:

標(biāo)注1,2,3:將需要發(fā)送給服務(wù)器的數(shù)據(jù)構(gòu)造為指令

標(biāo)注4,5,6:將服務(wù)器返回的數(shù)據(jù)用于刷新UI界面

標(biāo)注7,8:客戶端與服務(wù)器之間傳遞指令和返回的數(shù)據(jù)

標(biāo)注9,10:將指令送給指令驅(qū)動(dòng)模型處理,得到返回值

標(biāo)注11,12:服務(wù)器端與數(shù)據(jù)庫交互部分

移動(dòng)應(yīng)用要訪問服務(wù)器,需要通過HTTP協(xié)議向服務(wù)器發(fā)送信息,由于JSON格式[6,7]在傳輸效率上優(yōu)于其它數(shù)據(jù)傳輸格式,因此本文在設(shè)計(jì)接口架構(gòu)時(shí),使用JSON數(shù)據(jù)格式來傳遞信息.網(wǎng)絡(luò)接口通過URL來訪問,URL可以視為一個(gè)導(dǎo)向,移動(dòng)端在請(qǐng)求URL時(shí)需要攜帶相應(yīng)的請(qǐng)求數(shù)據(jù),通常一個(gè)URL對(duì)應(yīng)著固定的請(qǐng)求數(shù)據(jù)和返回?cái)?shù)據(jù).由于URL與傳輸數(shù)據(jù)具有這種強(qiáng)關(guān)聯(lián)的關(guān)系,本文把URL視為操作碼,將URL與傳輸數(shù)據(jù)抽象為一個(gè)整體,即指令,把指令視為網(wǎng)絡(luò)請(qǐng)求傳輸?shù)幕緮?shù)據(jù)單位,指令包含了URL和傳輸數(shù)據(jù)所表達(dá)的信息.

在移動(dòng)端構(gòu)造請(qǐng)求指令后,通過指令發(fā)送器發(fā)送到服務(wù)器,服務(wù)器通過指令解析器解析出具體的指令,并把指令交給指令驅(qū)動(dòng)模型處理,得到指令驅(qū)動(dòng)模型的返回結(jié)果并返回給移動(dòng)端.其中指令發(fā)送和指令解析是網(wǎng)絡(luò)數(shù)據(jù)傳輸過程,它們的任務(wù)就是傳遞指令,而與具體的URL和請(qǐng)求數(shù)據(jù)無關(guān),這樣可以屏蔽掉網(wǎng)絡(luò)傳輸過程,讓程序的編寫和調(diào)試更加方便,也方便將請(qǐng)求接口函數(shù)化.指令驅(qū)動(dòng)模型是服務(wù)器端與網(wǎng)絡(luò)傳輸無關(guān)的運(yùn)行單元,在移動(dòng)端構(gòu)造的請(qǐng)求指令是可以直接用于對(duì)應(yīng)指令驅(qū)動(dòng)模型的,這就滿足了數(shù)據(jù)一致性,讓移動(dòng)應(yīng)用調(diào)用接口如同調(diào)用本地函數(shù),這給程序的調(diào)試帶來了極大的便利.在這種模式下,當(dāng)需要修改功能或者是添加新功能時(shí),只需要修改指令驅(qū)動(dòng)模型就可以完成,極大的提高了程序的可擴(kuò)展性.

2.3 指令驅(qū)動(dòng)模型和構(gòu)造請(qǐng)求指令的設(shè)計(jì)

在整個(gè)網(wǎng)絡(luò)接口架構(gòu)中,指令驅(qū)動(dòng)模型和構(gòu)造請(qǐng)求指令是一套完整的體系,獨(dú)立在網(wǎng)絡(luò)傳輸之外,如果部署到同一臺(tái)設(shè)備仍然可以執(zhí)行,構(gòu)造的請(qǐng)求指令就是要投入指令驅(qū)動(dòng)模型中來得到返回結(jié)果,本文采用面向?qū)ο蟮乃枷雽?duì)其進(jìn)行設(shè)計(jì).

在大多數(shù)需要與數(shù)據(jù)庫交互的程序中,基本上都是把數(shù)據(jù)庫的每張表看作一個(gè)類,表里的每一行看為一個(gè)對(duì)象,正是由于這種面向?qū)ο蟮乃枷耄诔绦蚺c數(shù)據(jù)庫交互方面誕生了不少優(yōu)秀的框架[8,9].而移動(dòng)應(yīng)用向服務(wù)器發(fā)送請(qǐng)求,最終也是對(duì)服務(wù)器數(shù)據(jù)庫進(jìn)行一定的操作,這些操作是面向數(shù)據(jù)庫表的抽象數(shù)據(jù)類型的,因此移動(dòng)應(yīng)用的網(wǎng)絡(luò)請(qǐng)求可以根據(jù)具體操作的抽象數(shù)據(jù)類型來劃分,所以指令的操作碼部分應(yīng)該包含類和對(duì)類的操作,指令的數(shù)據(jù)部分可能有很多參數(shù),為了更好的組織代碼,提高代碼質(zhì)量,對(duì)于操作碼中的每個(gè)操作,指令中都需要有對(duì)應(yīng)所有參數(shù)的抽象數(shù)據(jù)類型.指令結(jié)構(gòu)如圖3所示.事實(shí)上,對(duì)一個(gè)類的操作并不會(huì)很多,而且可能只是增刪改查,所以很多指令的操作數(shù)部分只需要類本身對(duì)象就足夠了.如果嚴(yán)格按照每個(gè)操作對(duì)應(yīng)的參數(shù)創(chuàng)建抽象參數(shù)對(duì)象,在移動(dòng)端編程時(shí)填充指令對(duì)象就會(huì)方便很多,且不易出錯(cuò),這在一定程度上可以提高開發(fā)效率,提高系統(tǒng)可擴(kuò)展性.

圖3 本文提出的指令格式Fig.3 Instruction format proposed in this paper

指令驅(qū)動(dòng)模型是從面向?qū)ο蟮乃枷氤霭l(fā),它需要實(shí)現(xiàn)的功能是能夠執(zhí)行相應(yīng)的指令,返回執(zhí)行結(jié)果.所謂指令驅(qū)動(dòng),就是模型內(nèi)部的執(zhí)行過程是靠指令來驅(qū)動(dòng)的.指令驅(qū)動(dòng)模型是處理請(qǐng)求指令的核心,所以模型在使用時(shí)應(yīng)該具有良好的可擴(kuò)展性,在設(shè)計(jì)指令驅(qū)動(dòng)模型時(shí)需要充分考慮到程序是否具有低耦合高內(nèi)聚的特性.

本文提出的指令驅(qū)動(dòng)模型具有處理請(qǐng)求指令的功能,而對(duì)請(qǐng)求指令的處理是通過指令的操作碼實(shí)現(xiàn)對(duì)指令操作數(shù)的處理.由于設(shè)計(jì)指令時(shí),指令能夠通過指令要操作的類進(jìn)行劃分,指令驅(qū)動(dòng)模型就可以根據(jù)這一特點(diǎn),分析指令的操作碼然后把指令交到具體類的操作對(duì)象,由具體的操作對(duì)象對(duì)指令的操作數(shù)處理并返回處理結(jié)果.所以用于處理操作數(shù)的對(duì)象也會(huì)由類來劃分,這樣就會(huì)保證程序的可擴(kuò)展性.當(dāng)然,具體類的操作對(duì)象需要注冊(cè)到指令驅(qū)動(dòng)模型中,以保證指令驅(qū)動(dòng)模型在收到指令后可以正常運(yùn)作.

因此,在驅(qū)動(dòng)模型中需要一個(gè)具體操作對(duì)象的管理器來管理這些對(duì)象,在收到指令后可以分發(fā)給具體的操作對(duì)象去處理.由于指令是有格式的,具體的操作對(duì)象也具備一定的格式才能正常處理對(duì)應(yīng)的指令.因此不是任何一個(gè)對(duì)象都可以通過指令驅(qū)動(dòng)模型處理,也不是任何一個(gè)對(duì)象都可以注冊(cè)到指令驅(qū)動(dòng)模型中作為具體操作對(duì)象.因此,本驅(qū)動(dòng)模型中還具備一個(gè)分析器,不僅可以實(shí)現(xiàn)注冊(cè)操作對(duì)象時(shí)對(duì)操作對(duì)象的分析,而且能夠完成模型執(zhí)行指令時(shí)對(duì)指令的分析,從而保證模型的健壯性.另外,本模型具備異常處理模塊,因開發(fā)時(shí)因?yàn)殄e(cuò)誤的使用模型而使程序不正常運(yùn)行,能夠報(bào)出異常,并可以提示異常原因,從而提高開發(fā)效率.

在使用指令驅(qū)動(dòng)模型編程時(shí),只需要編寫不同類別的具體操作對(duì)象然后注冊(cè)到模型中.當(dāng)然,操作對(duì)象必須可以處理相應(yīng)指令,而指令和操作對(duì)象的關(guān)系就如函數(shù)的形參與函數(shù)的關(guān)系.因而,在本文設(shè)計(jì)的框架下,指令處理后的返回結(jié)果是任意的.如果把操作對(duì)象類比于函數(shù),這里的返回結(jié)果任意性不是說函數(shù)的返回值不需要定義,而是可以將返回值定義為任何類型,也即是對(duì)于同一個(gè)操作碼,操作對(duì)象可以把返回值定義任何類型,在將結(jié)果返回時(shí)都可以正常接收返回?cái)?shù)據(jù).這是由于,如果調(diào)用者需要調(diào)用模型處理一條指令,在調(diào)用模型之前它是知道需要的返回結(jié)果類型的.操作對(duì)象返回結(jié)果的任意性可以提高工作效率,簡化代碼,減少不必要的前后臺(tái)數(shù)據(jù)協(xié)商.

2.4 網(wǎng)絡(luò)數(shù)據(jù)傳輸設(shè)計(jì)

在網(wǎng)絡(luò)數(shù)據(jù)傳輸中,本文所設(shè)計(jì)的指令發(fā)送器和指令接收器只需要完成指令的前后臺(tái)傳遞,具有傳輸JSON數(shù)據(jù)的功能.

圖4 網(wǎng)絡(luò)數(shù)據(jù)傳輸流程Fig.4 Transmission process of network data

在移動(dòng)應(yīng)用工程中,出于網(wǎng)絡(luò)通訊安全性的考慮,往往需要對(duì)指令進(jìn)行加密,而且操作數(shù)具有不同的特性,如圖片資源和普通參數(shù),因此需要對(duì)指令進(jìn)行分類,此分類不同于將指令按操作碼的類別劃分,前者相當(dāng)于指令的標(biāo)簽,后者是指令中操作碼具有的性質(zhì).因此本研究在設(shè)計(jì)網(wǎng)絡(luò)數(shù)據(jù)傳輸時(shí),需要指令發(fā)送器可以區(qū)分指令的標(biāo)簽,根據(jù)指令的標(biāo)簽信息對(duì)指令進(jìn)行相應(yīng)的操作,在向服務(wù)器發(fā)送指令時(shí),攜帶著指令的標(biāo)簽信息,構(gòu)造擴(kuò)展指令,方便服務(wù)器對(duì)指令的正確解析.依據(jù)擴(kuò)展指令可以完成指令的發(fā)送和接收,然而在返回?cái)?shù)據(jù)的傳輸方面,就會(huì)略顯復(fù)雜,由于一條指令的返回結(jié)果具有任意性,這就給返回?cái)?shù)據(jù)的接收帶來了挑戰(zhàn),為了方便返回?cái)?shù)據(jù)的接收和解析,可以對(duì)指令好返回?cái)?shù)據(jù)統(tǒng)一化處理,都采用擴(kuò)展指令的形式封裝.事實(shí)上,指令和返回?cái)?shù)據(jù)都是一種抽象數(shù)據(jù)類型,因此可以統(tǒng)一化處理,使用統(tǒng)一的擴(kuò)展指令來傳遞,使網(wǎng)絡(luò)數(shù)據(jù)傳輸過程仍然具備前后端分離的特性.擴(kuò)展指令由附加信息和指令/返回?cái)?shù)據(jù)構(gòu)成.

本文設(shè)計(jì)網(wǎng)絡(luò)數(shù)據(jù)傳輸?shù)牧鞒虨橹噶畎l(fā)送器分析指令標(biāo)簽,生成擴(kuò)展指令發(fā)送到指令接收器,指令接收器解析出指令并傳遞到指令驅(qū)動(dòng)模型,指令接收器拿到對(duì)應(yīng)指令返回?cái)?shù)據(jù)后生成擴(kuò)展指令返回給指令發(fā)送器,指令發(fā)送器解析出返回?cái)?shù)據(jù).統(tǒng)一化處理指令和返回?cái)?shù)據(jù),屏蔽了網(wǎng)絡(luò)傳輸過程,提高了開發(fā)效率和程序的可擴(kuò)展性,并且給程序的調(diào)試帶來了便利.網(wǎng)絡(luò)數(shù)據(jù)傳輸流程如圖4所示.

3 基于指令驅(qū)動(dòng)模型的移動(dòng)應(yīng)用通訊接口框架實(shí)現(xiàn)

Java是一個(gè)廣泛使用的面向?qū)ο蟮木W(wǎng)絡(luò)編程語言,其具有良好的可移植性,跨平臺(tái)性,安全性,被廣泛應(yīng)用在各種場景的程序開發(fā)[10],本文使用Java編程語言面向Android應(yīng)用實(shí)現(xiàn)基于指令驅(qū)動(dòng)模型的移動(dòng)應(yīng)用通訊接口架構(gòu).

3.1 指令驅(qū)動(dòng)模型的實(shí)現(xiàn)

指令驅(qū)動(dòng)模型是本文設(shè)計(jì)架構(gòu)的基礎(chǔ)功能模塊,因此在實(shí)現(xiàn)架構(gòu)前需要先實(shí)現(xiàn)指令驅(qū)動(dòng)模型.指令驅(qū)動(dòng)模型模塊需要實(shí)現(xiàn)的是指令的實(shí)現(xiàn)和驅(qū)動(dòng)模型的實(shí)現(xiàn).指令包含操作碼和操作數(shù),操作碼可以根據(jù)要操作的實(shí)體類進(jìn)行劃分,故把操作碼設(shè)計(jì)為“實(shí)體類.具體操作”,對(duì)同一個(gè)實(shí)體類操作的指令使用同一個(gè)指令類.在用Java實(shí)現(xiàn)時(shí),對(duì)于每一個(gè)實(shí)體類都編寫一個(gè)對(duì)應(yīng)的指令類并統(tǒng)一命名規(guī)范,指令類命名為“要操作實(shí)體類加后綴Come”,操作碼字段使用request.操作對(duì)象要對(duì)指令對(duì)象操作,需要有對(duì)應(yīng)指令對(duì)象的屬性,把操作對(duì)象統(tǒng)一命名“實(shí)體類+Actor”.

指令驅(qū)動(dòng)模型可以根據(jù)指令對(duì)象的request的實(shí)體類標(biāo)識(shí)找到具體的操作對(duì)象,根據(jù)request的具體操作標(biāo)識(shí)找到具體的操作方法,進(jìn)而處理指令和返回結(jié)果.request字段與操作對(duì)象其中的方法存在映射關(guān)系,如圖5所示.驅(qū)動(dòng)模型根據(jù)映射關(guān)系正確的處理指令,可以使用Java編程語言的高級(jí)特性-注解[11,12]和反射編程.通過在Actor類中添加相應(yīng)的注解說明Come和Actor之間的映射關(guān)系.

圖5 Come指令和Actor的映射關(guān)系Fig.5 Mapping relationship between come instruction and actor

通過定義注解(@Come,@Actor,@Action)然后使用在Actor類中,就可以通過類似與user.register來定位到UserActor中的register方法.當(dāng)然UserActor需要提前注冊(cè)到驅(qū)動(dòng)模型中.

定義指令驅(qū)動(dòng)模型的控制器為Context類,實(shí)現(xiàn)為單例模式,Context類的方法應(yīng)該有addActor():向Context注冊(cè)Actor類,getComeClass():通過Come對(duì)象的類名獲取類的字節(jié)碼對(duì)象,這個(gè)方法主要是和利用JSON解析指令相關(guān),showWorks():此方法用于顯示出注冊(cè)到Context中的Actor類的所有指令到處理方法的映射路線,back(Come),此方法用于對(duì)接收Come對(duì)象并產(chǎn)生返回結(jié)果.

分析器作用是分析Come對(duì)象中request字段是否符合規(guī)范,以及注冊(cè)到Context的Actor類是否符合規(guī)范.如果不符合規(guī)范,交由異常處理模塊進(jìn)行相應(yīng)處理.操作對(duì)象管理器負(fù)責(zé)實(shí)例化Actor對(duì)象,并將收到的Come指令填充其中的Come屬性,根據(jù)Come指令的request字段調(diào)用@Action對(duì)應(yīng)的方法,如果Actor對(duì)象中含有該方法返回值類型的引用,調(diào)用方法前會(huì)把返回值的引用實(shí)例化.

每個(gè)操作碼對(duì)應(yīng)這一種返回?cái)?shù)據(jù)類型,但是開發(fā)人員在使用驅(qū)動(dòng)模型時(shí)是不希望總是寫強(qiáng)制類型轉(zhuǎn)化的,因此在實(shí)現(xiàn)Context的back()方法時(shí),通過利用Java的泛型編程消除強(qiáng)制類型轉(zhuǎn)化步驟.

測(cè)試指令驅(qū)動(dòng)模型:

public class TestCome {

private String request;

}

@Actor(name = “user”)

public class TestActor {

@Come

TestCome come;

TestBack testBack;

@Action(name = “test”)

TestBack getBack(){

testBack.setData(“Hello World!”);

return testBack;

}

@Action(name = “testList”)

List getList(){

List list=new ArrayList();

return list;

}

}

//注冊(cè)TestActor

Context context=Context.getContext();

context.addActor(TestActor.class);

context.showWorks();

TestCome comeData=new TestCome();

//測(cè)試返回TestBack類型

comeData.setRequest(“user.test”);

TestBack backData=context.back(comeData);

//測(cè)試返回list類型

comeData.setRequest(“user.testList”);

List string1=context.back(comeData);

3.2 網(wǎng)絡(luò)數(shù)據(jù)傳輸?shù)膶?shí)現(xiàn)

在實(shí)現(xiàn)指令和返回?cái)?shù)據(jù)的傳遞方面,擴(kuò)展指令的定義非常重要,擴(kuò)展指令包含附加信息和指令/返回?cái)?shù)據(jù),附加信息很少,只需要定義幾個(gè)字段即可,但是不同的指令和數(shù)據(jù)具有不同的數(shù)據(jù)類型,如果在擴(kuò)展指令類中一一定義,會(huì)使擴(kuò)展指令對(duì)象變的極為復(fù)雜,而且影響程序的可擴(kuò)展性.所以本文實(shí)現(xiàn)的擴(kuò)展指令對(duì)象中的指令或數(shù)據(jù)屬于字符串類型,字段定義為data,用來存放JSON格式的指令或數(shù)據(jù),這樣就可以對(duì)指令和數(shù)據(jù)進(jìn)行統(tǒng)一化實(shí)現(xiàn).指令接收器接收到擴(kuò)展指令后需要對(duì)指令反序列化,解析成Java對(duì)象,因此在擴(kuò)展指令的附加信息中需要有指令類的類名,指令接收器就可以調(diào)用Context對(duì)象的getComeClass拿到指令的字節(jié)碼,進(jìn)而將其解析為Java對(duì)象.本文把擴(kuò)展指令定義為Body類,字段包括name,data和key,其中name是指令或返回?cái)?shù)據(jù)的類名,data是指令或返回?cái)?shù)據(jù)的JSON格式字符串,key用于請(qǐng)求驗(yàn)證,擴(kuò)展指令的傳遞同樣需要JSON數(shù)據(jù)傳輸格式.

指令接收器用servlet實(shí)現(xiàn),定義一個(gè)servlet接收J(rèn)SON字符串形式的Body,定義一個(gè)數(shù)據(jù)處理類,用于JSON解析和數(shù)據(jù)加密.指令接收器只負(fù)責(zé)將擴(kuò)展指令Body中的Come通過數(shù)據(jù)處理對(duì)象解析出來,交給指令驅(qū)動(dòng)模型處理,拿到返回?cái)?shù)據(jù)再通過數(shù)據(jù)處理對(duì)象包裝成Body作為返回體.數(shù)據(jù)處理對(duì)象用來將數(shù)據(jù)對(duì)象化,進(jìn)行token認(rèn)證,數(shù)據(jù)加密和解密處理[13].這種模式下只需要?jiǎng)?chuàng)建一個(gè)servlet即可,具體的指令處理與指令接收隔離開,指令驅(qū)動(dòng)模型與指令接收器是隔離的,可以極大的提高程序的易讀性和可擴(kuò)展性.

對(duì)于指令發(fā)送器,本文采用Retrofit封裝網(wǎng)絡(luò)請(qǐng)求模塊,讓指令發(fā)送器負(fù)責(zé)將指令封裝為擴(kuò)展指令Body,對(duì)其發(fā)送與接收,采用異步的請(qǐng)求處理方式,使用谷歌的Gson進(jìn)行JSON數(shù)據(jù)解析.在具體請(qǐng)求代碼塊中構(gòu)造請(qǐng)求指令,向指令發(fā)送器傳遞Come對(duì)象并接收返回對(duì)象,并且收到返回?cái)?shù)據(jù)后可以通過doSucces和doFailure方法刷新UI界面.同樣的,指令發(fā)送器也利用數(shù)據(jù)處理對(duì)象將指令轉(zhuǎn)化為Body發(fā)送或者將接收到的Body中的返回?cái)?shù)據(jù)轉(zhuǎn)化為Java對(duì)象,同時(shí)需要根據(jù)Come指令的類別(比如需要加密)對(duì)指令進(jìn)行相應(yīng)的處理.

圖6 整體架構(gòu)的實(shí)現(xiàn)Fig.6 Implementation of overall architecture

指令發(fā)送器和指令接收器交互只用Body進(jìn)行,因此指令發(fā)送器只需編寫一個(gè)請(qǐng)求方法,這簡化了網(wǎng)絡(luò)請(qǐng)求編寫的復(fù)雜度.數(shù)據(jù)處理對(duì)象與指令接收器中的數(shù)據(jù)處理對(duì)象類似,實(shí)現(xiàn)數(shù)據(jù)對(duì)象之間的解析轉(zhuǎn)化,其中將返回Body中的放回?cái)?shù)據(jù)解析成具體對(duì)象是一個(gè)難點(diǎn),因?yàn)橛蒍SON類型字符串解析成Java對(duì)象,需要有Java對(duì)象的字節(jié)碼對(duì)象或者對(duì)象類型,如果接收一個(gè)帶有泛型的Map或者List,運(yùn)行時(shí)泛型就會(huì)被擦除,導(dǎo)致無法正確解析到想要的對(duì)象,針對(duì)此問題,本文通過Gson的TypeToken獲取具體對(duì)象的Type,Type type = new TypeToken(){}.getType();再進(jìn)行相應(yīng)的解析,但是每個(gè)請(qǐng)求得到的返回類型有差異,為了減少編寫復(fù)雜度,本文采用面向?qū)ο蟮睦^承特性,創(chuàng)建DoBack抽象類繼承Gson的TypeToken,完美的解決了這個(gè)問題.

調(diào)用請(qǐng)求只需要構(gòu)造Come指令,交給指令發(fā)送器,就可以獲得返回對(duì)象,進(jìn)而進(jìn)行相應(yīng)的處理,處理的方法也是在UI線程中的,可直接刷新界面.這樣一來,就完成了Come指令到返回?cái)?shù)據(jù)端到端的處理過程,提高程序的可讀性和開發(fā)效率.

3.3 整體框架的實(shí)現(xiàn)

在定義好擴(kuò)展指令Body類,指令發(fā)送器,指令接收器之后,就在應(yīng)用與服務(wù)器之間生成了一條數(shù)據(jù)傳輸線,在編寫請(qǐng)求時(shí),只需要面向指令驅(qū)動(dòng)模型進(jìn)行編寫.測(cè)試時(shí)在數(shù)據(jù)傳輸線沒有錯(cuò)誤的情況下,只需要對(duì)具體請(qǐng)求塊和指令驅(qū)動(dòng)模型進(jìn)行測(cè)試,具體請(qǐng)求塊的測(cè)試屬于客戶端獨(dú)立的測(cè)試,指令驅(qū)動(dòng)模型屬于服務(wù)器端獨(dú)立的測(cè)試,從而可以提高測(cè)試效率.整體架構(gòu)的實(shí)現(xiàn)如圖6所示.

3.4 框架實(shí)現(xiàn)具體代碼

具體請(qǐng)求塊:使用一個(gè)抽象類繼承GSON的TypeToken,使之具有g(shù)etType方法,用于獲取真正的類型.

public abstract class DoBack extends TypeToken{

protected DoBack(Object object){

Api.getApi().go(object,this);

}

public abstract void doSuccess(T t);

public abstract void doFailure();}

指令發(fā)送器:使用Retrofit框架定義網(wǎng)絡(luò)請(qǐng)求接口傳輸Body的JSON字符串:

@FormUrlEncoded

@POST(“ActionService”)

Call request(@Field(“data”)String body);

創(chuàng)建Api類定義Retrofit的HttpClient,JSON參數(shù)解析等基本配置,getApi()得到單例對(duì)象Api,go(object,this)是請(qǐng)求方法,object是Come對(duì)象,用DoBack本身作為參數(shù),用于準(zhǔn)確接收想要的返回類型,配備返回?cái)?shù)據(jù)的處理方法.go方法定義如下:

public void go(final T t,final DoBack doBack){

String data= BCB.createBodyString(t);

Call call = getOwnApi().request(data);

call.enqueue(new Callback(){

@Override

public void onResponse(Call call,Response response){

if(response.body()!= null){

Object obj=BCB.ComeOrBack(response.body(),doBack.getType());

if(obj == null)

doBack.doFailure();

else

doBack.doSuccess(obj);

} else {

doBack.doFailure();

}

}

@Override

public void onFailure(Call call,Throwable t){

doBack.doFailure();

}

});}

BCB是定義的數(shù)據(jù)處理對(duì)象,可以看到傳入doBack的doSuccess()方法的obj是解析好的返回?cái)?shù)據(jù)對(duì)象,因此在具體請(qǐng)求塊就可以直接利用返回?cái)?shù)據(jù)對(duì)象進(jìn)行相應(yīng)的刷新頁面.

指令接收器:

data=req.getParameter(“data”);

body=BCB.Body(data);

if(BCB.checkTime(body)==false){

onDefeat();

return;

}

String result=

BCB.createBodyString(

context.back(

BCB.ComeOrBack(body,context.getComeClass(body.getName()))));

if(result==null){

onDefeat();

return;

}

writer.write(result);

其中context是指令驅(qū)動(dòng)模型的控制器,先調(diào)用getComeClass()得到傳到指令接收器的Come指令對(duì)象的字節(jié)碼文件,調(diào)用BCB解析出Come對(duì)象,調(diào)用context.back()得到返回?cái)?shù)據(jù)對(duì)象,進(jìn)而包裝為Body的JSON字符串返回.

4 基于Android 應(yīng)用的網(wǎng)絡(luò)接口實(shí)現(xiàn)

樣例APP實(shí)現(xiàn)user的注冊(cè)登錄,登錄成功顯示新聞列表,數(shù)據(jù)庫連接使用Hibernate框架,user表字段uid,username,password.news表字段 nid,title,content.IDE使用AS和eclipse.

定義UserActor和NewsActor,注冊(cè)到指令驅(qū)動(dòng)模型.兩個(gè)Actor面對(duì)的Come都是UserCome,UserCome中只有一個(gè)request字段和一個(gè)User對(duì)象.UserActor對(duì)應(yīng)的指令是user.login和user.register,NewsActor對(duì)應(yīng)的指令是news.getList.編寫APP頁面并加入具體請(qǐng)求塊,用于注冊(cè)的具體請(qǐng)求塊如下:

User user=new User();

user.setUsername(username.getText().toString());

user.setPassword(password.getText().toString());

UserCome userCome=new UserCome();

userCome.setRequest(“user.register”);

userCome.setUser(user);

DoBackdoBack=new DoBack(userCome){

@Override

public void do Success(String s){

T;

}

@Override

public void doFailure(){

F;

}

};

獲取News的具體請(qǐng)求塊如下:

userCome.setRequest(“news.getList”);

DoBack> doBack1=new DoBack>(userCome){

@Override

public void doSuccess(List news){

T;

}

@Override

public void doFailure(){

F;

}

};

登陸模塊與此類似.指令驅(qū)動(dòng)模型編寫在Actor中使用Hibernate進(jìn)行數(shù)據(jù)庫交互.例如user.register和news.getList如下所示:

@Actor(name = “user”)

public class UserActor {

@Come

UserCome userCome;

@Action(name = “register”)

String register(){

User user=

HibernateUtil.getobj(User.class,“username”,

userCome.getUser().getUsername());

if(user==null){

HibernateUtil.save(userCome.getUser());

return “注冊(cè)成功”;

}else {

return “用戶名已存在”;

}

}

}

@Actor(name = “news”)

public class NewsActor {

@Come

UserCome userCome;

@Action(name = “getList”)

List get(){

List list=

HibernateUtil.listByHql(“from News”,null);

return list;

}

}

捏造UserCome對(duì)登錄、注冊(cè)和獲取新聞列表接口測(cè)試,測(cè)試結(jié)果如圖7所示.

圖7 部分測(cè)試結(jié)果示意圖Fig.7 Illustration of some testing results

采用本文提出的框架進(jìn)行開發(fā),開發(fā)測(cè)試和擴(kuò)展過程歸約到對(duì)指令驅(qū)動(dòng)模型開發(fā)測(cè)試和擴(kuò)展,屏蔽了網(wǎng)絡(luò)傳輸過程,提高開發(fā)效率.如果采用Retrofit(請(qǐng)求框架)+Struts2或SpringMVC(后臺(tái)框架)搭建應(yīng)用框架,則需要對(duì)每個(gè)請(qǐng)求接口編寫請(qǐng)求方法,在請(qǐng)求時(shí)指向URL并攜帶參數(shù),后臺(tái)編寫對(duì)應(yīng)的Action類或Controller類來接受參數(shù)并進(jìn)行處理.使用Struts2框架或者SpringMVC框架,前端后臺(tái)是通過網(wǎng)絡(luò)傳輸這一過程進(jìn)行分割,通過URL傳遞參數(shù)進(jìn)行溝通,這無疑會(huì)使開發(fā)過程脫離不了網(wǎng)絡(luò)傳輸,在編寫調(diào)試方面都會(huì)提高復(fù)雜度.表1給出了各框架在開發(fā)模式、編碼、測(cè)試、維護(hù)與擴(kuò)展進(jìn)行理論上的比較,并總結(jié)了應(yīng)用各框架的開發(fā)復(fù)雜度和各框架的作用.

表1 各個(gè)框架詳細(xì)對(duì)比Table 1 Comparison with some common frameworks

在開發(fā)模式上,本文將URL和參數(shù)抽象為指令,結(jié)合指令發(fā)送器和接收器屏蔽了網(wǎng)絡(luò)傳輸過程,使接口的請(qǐng)求僅依賴指令驅(qū)動(dòng)模型,這給編碼測(cè)試和擴(kuò)展提供了便利.

5 結(jié) 論

本文提出了基于指令驅(qū)動(dòng)模型對(duì)移動(dòng)編程通信接口設(shè)計(jì),把整個(gè)通信過程分解為構(gòu)造請(qǐng)求指令,指令發(fā)送器,令接收器,指令驅(qū)動(dòng)模型,進(jìn)而產(chǎn)生了指令到網(wǎng)絡(luò)傳輸?shù)街噶铗?qū)動(dòng)模型的開發(fā)框架,通過請(qǐng)求指令化,在保證模塊隔離性的同時(shí)也保證了前后臺(tái)數(shù)據(jù)的一致性,指令驅(qū)動(dòng)模型成為實(shí)際數(shù)據(jù)交互的載體,保證程序的擴(kuò)展性,提高測(cè)試效率.這種架構(gòu)可以屏蔽具體網(wǎng)絡(luò)傳輸,降低數(shù)據(jù)耦合度,簡化移動(dòng)端和服務(wù)器端的代碼編寫,根據(jù)該架構(gòu)開發(fā)基于Android系統(tǒng)的 APP應(yīng)用并對(duì)比了各個(gè)框架的使用情況,驗(yàn)證了此架構(gòu)的有效性和實(shí)用性.

在請(qǐng)求指令化后,指令就成為移動(dòng)應(yīng)用請(qǐng)求的基本數(shù)據(jù)單元,移動(dòng)端的請(qǐng)求被抽象為一條條指令的發(fā)送.通常在移動(dòng)應(yīng)用中,一個(gè)界面可能具有很多可能要發(fā)送的指令,而且指令具有一定的邏輯關(guān)系.因此,可以在本文提出的編程架構(gòu)基礎(chǔ)上進(jìn)一步研究指令的對(duì)應(yīng)概念,如指令的順序執(zhí)行,分支結(jié)構(gòu)和循環(huán)結(jié)構(gòu),以適應(yīng)具體開發(fā)場景.

猜你喜歡
網(wǎng)絡(luò)接口發(fā)送器接收器
變電站網(wǎng)絡(luò)接口物理防護(hù)系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
移頻發(fā)送器冗余切換設(shè)計(jì)研究
JXG-50S型相敏軌道電路接收器自動(dòng)測(cè)試臺(tái)
埃及
用于獲取車輛中的旋轉(zhuǎn)構(gòu)件的旋轉(zhuǎn)角度的傳感器組件
傳感器世界(2017年4期)2017-03-23 10:50:49
淺析CTC與GSM-R系統(tǒng)網(wǎng)絡(luò)接口及路由配置改進(jìn)措施
ZPW-2000A軌道電路接收器冗余電路存在問題分析及對(duì)策
網(wǎng)絡(luò)設(shè)置管理
從兩起故障談ZPW-2000發(fā)送盒報(bào)警檢測(cè)的改進(jìn)
京滬高鐵GSM-R網(wǎng)絡(luò)接口監(jiān)測(cè)網(wǎng)關(guān)子系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
通化县| 潢川县| 青浦区| 诸城市| 赤水市| 沈阳市| 桐乡市| 屯留县| 阿拉善盟| 阿克陶县| 达日县| 泰安市| 台安县| 安阳市| 张家川| 上高县| 永兴县| 嵩明县| 昌宁县| 榆社县| 广西| 娱乐| 盐池县| 昔阳县| 皋兰县| 南乐县| 乳山市| 太谷县| 安泽县| 平南县| 通化市| 金川县| 全椒县| 乌拉特中旗| 东乡族自治县| 新竹市| 永济市| 临沭县| 凌云县| 镇康县| 防城港市|