• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

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

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

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

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

      2.1 通用開發(fā)模式

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

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

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

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

      本文提出的編程架構(gòu)共分為四個模塊,構(gòu)造請求指令,指令發(fā)送器,指令接收器,指令驅(qū)動模型,其中構(gòu)造請求指令和指令驅(qū)動模型是一組,指令發(fā)送器和指令接收器是一組.整個流程如圖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ū)動模型處理,得到返回值

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      指令驅(qū)動模型可以根據(jù)指令對象的request的實(shí)體類標(biāo)識找到具體的操作對象,根據(jù)request的具體操作標(biāo)識找到具體的操作方法,進(jìn)而處理指令和返回結(jié)果.request字段與操作對象其中的方法存在映射關(guān)系,如圖5所示.驅(qū)動模型根據(jù)映射關(guān)系正確的處理指令,可以使用Java編程語言的高級特性-注解[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需要提前注冊到驅(qū)動模型中.

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

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

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

      測試指令驅(qū)動模型:

      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;

      }

      }

      //注冊TestActor

      Context context=Context.getContext();

      context.addActor(TestActor.class);

      context.showWorks();

      TestCome comeData=new TestCome();

      //測試返回TestBack類型

      comeData.setRequest(“user.test”);

      TestBack backData=context.back(comeData);

      //測試返回list類型

      comeData.setRequest(“user.testList”);

      List string1=context.back(comeData);

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

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

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

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

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

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

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

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

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

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

      具體請求塊:使用一個抽象類繼承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ò)請求接口傳輸Body的JSON字符串:

      @FormUrlEncoded

      @POST(“ActionService”)

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

      創(chuàng)建Api類定義Retrofit的HttpClient,JSON參數(shù)解析等基本配置,getApi()得到單例對象Api,go(object,this)是請求方法,object是Come對象,用DoBack本身作為參數(shù),用于準(zhǔn)確接收想要的返回類型,配備返回數(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ù)處理對象,可以看到傳入doBack的doSuccess()方法的obj是解析好的返回數(shù)據(jù)對象,因此在具體請求塊就可以直接利用返回數(shù)據(jù)對象進(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ū)動模型的控制器,先調(diào)用getComeClass()得到傳到指令接收器的Come指令對象的字節(jié)碼文件,調(diào)用BCB解析出Come對象,調(diào)用context.back()得到返回數(shù)據(jù)對象,進(jìn)而包裝為Body的JSON字符串返回.

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

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

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

      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的具體請求塊如下:

      userCome.setRequest(“news.getList”);

      DoBack> doBack1=new DoBack>(userCome){

      @Override

      public void doSuccess(List news){

      T;

      }

      @Override

      public void doFailure(){

      F;

      }

      };

      登陸模塊與此類似.指令驅(qū)動模型編寫在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 “注冊成功”;

      }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對登錄、注冊和獲取新聞列表接口測試,測試結(jié)果如圖7所示.

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

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

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

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

      5 結(jié) 論

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

      在請求指令化后,指令就成為移動應(yīng)用請求的基本數(shù)據(jù)單元,移動端的請求被抽象為一條條指令的發(fā)送.通常在移動應(yīng)用中,一個界面可能具有很多可能要發(fā)送的指令,而且指令具有一定的邏輯關(guān)系.因此,可以在本文提出的編程架構(gòu)基礎(chǔ)上進(jìn)一步研究指令的對應(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型相敏軌道電路接收器自動測試臺
      埃及
      用于獲取車輛中的旋轉(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軌道電路接收器冗余電路存在問題分析及對策
      網(wǎng)絡(luò)設(shè)置管理
      從兩起故障談ZPW-2000發(fā)送盒報警檢測的改進(jìn)
      京滬高鐵GSM-R網(wǎng)絡(luò)接口監(jiān)測網(wǎng)關(guān)子系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
      苍南县| 盘山县| 大关县| 务川| 姚安县| 交口县| 敖汉旗| 原平市| 奉贤区| 宜春市| 株洲市| 苍南县| 枣强县| 赤峰市| 青铜峡市| 彩票| 岳普湖县| 麻阳| 高平市| 明光市| 彰化市| 黄平县| 洛扎县| 尚义县| 潍坊市| 巴林左旗| 嵩明县| 宁乡县| 环江| 永德县| 海林市| 成武县| 托里县| 平遥县| 洪泽县| 陆川县| 察隅县| 循化| 攀枝花市| 邛崃市| 龙江县|