引言對于第一點,我想說技術(shù)沒有高低貴賤之分,能把自己領(lǐng)域方向做到極致的才是最吊的。 所以說,web應(yīng)用既然有這么多的應(yīng)用場景,肯定有復(fù)雜的系統(tǒng)涉及到多線程問題。 本文要講述的是如何開發(fā)規(guī)范Java Web應(yīng)用。規(guī)范包括:如何分層、每一層的職責(zé)、層之間如何交互、數(shù)據(jù)如何流通等。 分層典型的web應(yīng)用分為三層,即:Controller層、Service層、Dao層。 如下圖所示: ![]() Controller層Controller層,我認(rèn)為是系統(tǒng)的Facade。職責(zé)包括以下幾點:
接收系統(tǒng)輸入常見的包括從request中提取path variable,query param,request payload、用戶認(rèn)證信息等。另外,Web 系列面試題和答案全部整理好了,微信搜索Java技術(shù)棧,在后臺發(fā)送:面試,可以在線閱讀。 數(shù)據(jù)校驗基本的數(shù)據(jù)校驗包括:數(shù)據(jù)類型,數(shù)據(jù)取值范圍、數(shù)據(jù)格式。舉個例子,假設(shè)有一個轉(zhuǎn)賬接口,其中有一個金額字段。這里對金額字段做的校驗包括:不能為負(fù)數(shù)。而業(yè)務(wù)型的檢查包括金額不能大于賬戶余額、不能大于賬戶類型所對應(yīng)的最大轉(zhuǎn)賬額度不應(yīng)該放在Controller層進(jìn)行校驗。 協(xié)議轉(zhuǎn)化協(xié)議轉(zhuǎn)化包含兩個方面。
系統(tǒng)內(nèi)部數(shù)據(jù)類型轉(zhuǎn)化 包括:BO轉(zhuǎn)化成DTO、BO轉(zhuǎn)化成VO。這幾種數(shù)據(jù)模型含義下一節(jié)會具體講述。 數(shù)據(jù)內(nèi)容協(xié)議轉(zhuǎn)化 舉個例子說明會更加容易理解。假設(shè)有一個Open API,功能是返回User信息。這個Open API對A公司開放的信息包括:昵稱、頭像兩個字段,而B公司是本公司的VIP用戶,對其開放的信息不僅包含昵稱、頭像還包括電話、email等隱私信息。 在Service層只有一個返回UserBO的接口,UserBO包含用戶所有的信息,在Controller層根據(jù)不同公司的類型,生成不同的UserDTO,此過程稱為數(shù)據(jù)內(nèi)容協(xié)議轉(zhuǎn)化。 數(shù)據(jù)傳輸格式協(xié)議轉(zhuǎn)化 包括:把對象序列化成json、xml格式數(shù)據(jù)、html頁面等 系統(tǒng)輸出把協(xié)議轉(zhuǎn)化之后的數(shù)據(jù),組裝成Http Response輸出給外部應(yīng)用。 定義系統(tǒng)接口一個系統(tǒng)提供了那些能力,則由系統(tǒng)接口決定的。接口包含三部分內(nèi)容:
Service層service層主要負(fù)責(zé)系統(tǒng)業(yè)務(wù)邏輯的處理。上面提到的轉(zhuǎn)賬金額上限的校驗應(yīng)該放在此層。service層根據(jù)業(yè)務(wù)系統(tǒng)的復(fù)雜度又可以劃分成多層。以兩層為例:
資源Service層 一般跟一張表、一個Dao對應(yīng)。在SOA領(lǐng)域里,把一部分高度內(nèi)聚的資源作為一個SOA Service,例如UserSerivce,OrderService等。其它應(yīng)用不應(yīng)該直接訪問User相關(guān)的數(shù)據(jù)庫,而應(yīng)該調(diào)用UserService。資源高度內(nèi)聚,便于管理和控制。 在分布式系統(tǒng)如此,在一個系統(tǒng)內(nèi)部也應(yīng)該如此。也就是說,一張表也可以作為一個資源,其它的Service不應(yīng)該直接訪問這張表,而應(yīng)該通過這張表對應(yīng)的Service來訪問。當(dāng)然,有些時候可以把幾張表的資源內(nèi)聚到一個Service當(dāng)中。 換句話說,Dao不應(yīng)該到處散落在不同的Service中,訪問資源應(yīng)該調(diào)用資源對應(yīng)的Serivce。資源Service層理論上應(yīng)該涉及很薄的、跟資源相關(guān)的業(yè)務(wù)邏輯。附加dao一些簡單的業(yè)務(wù)邏輯能力。另外一個職責(zé)就是數(shù)據(jù)類型轉(zhuǎn)換,也就是PO轉(zhuǎn)化為BO,后面會詳細(xì)講述。 聚合業(yè)務(wù)邏輯層 這一層是真正核心業(yè)務(wù)邏輯處理的地方,在資源Service層之上。完全負(fù)責(zé)處理業(yè)務(wù)邏輯,不用關(guān)心資源訪問。最新 Web 面試題整理好了,點擊Java面試庫小程序在線刷題。 對于不復(fù)雜的應(yīng)用系統(tǒng)來說,大部分的Service其實可以合為一層,有些特別復(fù)雜的業(yè)務(wù)邏輯可以單獨抽象出一層,切記Service角色要清晰。判斷是否清晰最簡單的方式就是能否自然的想出Service的名字。 另外插一句題外話,很多公司或者書籍提倡面向接口編程,導(dǎo)致一個很常見的現(xiàn)象就是一個Service包含兩部分:XXService和XXServiceImpl。這樣寫好處就是接口和實現(xiàn)分離,接口亦是文檔,清晰。壞處就是多了一個類。 我們不應(yīng)該不假思索的按照慣性思維去實踐,在剛提到的這種面向接口編程不是完全可取的。接口的本意是可以有多種實現(xiàn),也就是可能有多個子類。但是上面提到的這種Service基本上都只有一個實現(xiàn)類,那么接口的意義何在?當(dāng)然并不是說就不需要接口實現(xiàn)分離。 我覺得以下情況可以考慮分離:
很顯然對于大部分的web應(yīng)用,以上三點并不符合,所以我覺得沒必要接口實現(xiàn)分離,多出一個沒有意思類實在是很丑。 點擊關(guān)注公眾號,Java干貨及時送達(dá) Dao層dao層比較簡單,應(yīng)該只負(fù)責(zé)和數(shù)據(jù)庫打交道,不應(yīng)該涉及業(yè)務(wù)邏輯,只涉及跟數(shù)據(jù)存儲相關(guān)的邏輯。 數(shù)據(jù)類型數(shù)據(jù)類型一般分為以下幾種:PO、BO、VO、DTO、Model、POJO。 PO(persistence object)持久化對象,一般表示一張表,屬性跟表字段一一對應(yīng)。 BO (business object)業(yè)務(wù)對象,在業(yè)務(wù)組件中流通的對象。字段集合可能比PO多,也可能比PO少。一個PO可能對應(yīng)多個BO。 VO (view object)視圖對象,只用來給前端頁面渲染的數(shù)據(jù)結(jié)構(gòu)。 DTO (data transaction object)數(shù)據(jù)傳輸對象,在各個系統(tǒng)間傳輸?shù)膶ο?,一般需要實現(xiàn)Serializable接口。 Model表單數(shù)據(jù)模型,一般對應(yīng)request payload。 POJO (plain ordinary Java object)只用來表示數(shù)據(jù)類型,游離在系統(tǒng)業(yè)務(wù)之外的java bean。 數(shù)據(jù)類型和分層結(jié)合理論上每一種數(shù)據(jù)類型只能在特定的層中出現(xiàn)。po => dao層, 資源Service層 bo => Service層,Controller層 * vo、dto、model => Controller層。 推薦一個 Spring Boot 基礎(chǔ)教程及實戰(zhàn)示例:https://github.com/javastacks/spring-boot-best-practice 如下圖所示: ![]() 任何的規(guī)范都是靈活的,如果按照上面嚴(yán)格執(zhí)行的話,就會產(chǎn)生很多屬性基本一致的類,而且類型轉(zhuǎn)換代碼非常機(jī)械化。對于大部分簡單的系統(tǒng)來說,各個類型之間,字段幾乎是完全一致。 靈活的做法是下層的對象可以上升到上層,比如某一個資源沒有BO,也沒有VO,只有PO。也就是說PO存在于Dao,Service和Controller三層。但是反之則不行,例如VO、DTO、Model不應(yīng)該在Service層出現(xiàn),更不能在Dao層出現(xiàn)。所以最佳實踐則是最少要兩層。 如下圖所示: ![]() 另外需要注意一點就是:其它系統(tǒng)的DTO等于自身系統(tǒng)的PO,也就是說上面提到的所有的類型其實是相對于數(shù)據(jù)流的位置而定的。所以,在Service層流通的DTO其實是PO的角色。但是自身系統(tǒng)對外的DTO就不應(yīng)該在Service層出現(xiàn)。 結(jié)語做任何事情都需要規(guī)范,web開發(fā)亦是如此。規(guī)范的好處是:整潔、易維護(hù)、易理解。規(guī)范也是每個程序員進(jìn)階的必經(jīng)之路。上述對于分層和數(shù)據(jù)類型的理解都是個人對于項目開發(fā)的思考,可能跟其它規(guī)范有出入。 規(guī)范不是協(xié)議,規(guī)范是約定并不是強(qiáng)制,只要清晰可實踐即可。每個人都可以有自己的規(guī)范,但是需要要大部分人所能接受理解。 注:以上分層和類型的稱呼只是定義角色,具體系統(tǒng)中使用的叫法可以不一致。只要團(tuán)隊內(nèi)部約定好即可。 |
|
來自: 昵稱10087950 > 《JAVA》