首先解釋面上意思,service是業(yè)務(wù)層,dao是數(shù)據(jù)訪問層。
景洪網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)公司,景洪網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為景洪成百上千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請找那個(gè)售后服務(wù)好的景洪做網(wǎng)站的公司定做!
呵呵,這個(gè)問題我曾經(jīng)也有過,記得以前剛學(xué)編程的時(shí)候,都是在service里直接調(diào)用dao,service里面就new一個(gè)dao類對象,調(diào)用,其他有意義的事沒做,也不明白有這個(gè)有什么用,參加工作久了以后就會知道,業(yè)務(wù)才是工作中的重中之重。
我們都知道,標(biāo)準(zhǔn)主流現(xiàn)在的編程方式都是采用MVC綜合設(shè)計(jì)模式,MVC本身不屬于設(shè)計(jì)模式的一種,它描述的是一種結(jié)構(gòu),最終目的達(dá)到解耦,解耦說的意思是你更改某一層代碼,不會影響我其他層代碼,如果你會像spring這樣的框架,你會了解面向接口編程,表示層調(diào)用控制層,控制層調(diào)用業(yè)務(wù)層,業(yè)務(wù)層調(diào)用數(shù)據(jù)訪問層。初期也許都是new對象去調(diào)用下一層,比如你在業(yè)務(wù)層new一個(gè)DAO類的對象,調(diào)用DAO類方法訪問數(shù)據(jù)庫,這樣寫是不對的,因?yàn)樵跇I(yè)務(wù)層中是不應(yīng)該含有具體對象,最多只能有引用,如果有具體對象存在,就耦合了。當(dāng)那個(gè)對象不存在,我還要修改業(yè)務(wù)的代碼,這不符合邏輯。好比主板上內(nèi)存壞了,我換內(nèi)存,沒必要連主板一起換。我不用知道內(nèi)存是哪家生產(chǎn),不用知道多大容量,只要是內(nèi)存都可以插上這個(gè)接口使用。這就是MVC的意義。
接下來說你感覺service的意義,其實(shí)因?yàn)槟悻F(xiàn)在做東西分層次不是那么嚴(yán)格,在一個(gè)你們做東西業(yè)務(wù)本身也少,舉個(gè)最簡單的例子,你做一個(gè)分頁的功能,數(shù)據(jù)1000條,你20條在一個(gè)頁,你可以把這個(gè)功能寫成工具類封裝起來,然后在業(yè)務(wù)層里調(diào)用這個(gè)封裝的方法,這才是業(yè)務(wù)里真正干得事,只要沒訪問數(shù)據(jù)庫的,都要在業(yè)務(wù)里寫。
再有不明白的追問,這是經(jīng)驗(yàn)問題,呵呵,其實(shí)以后你就會懂。只是剛開始寫的代碼都是有個(gè)請求,我就去數(shù)據(jù)庫取,業(yè)務(wù)幾乎沒有。
煙囪式開發(fā)模式:
上述開發(fā)模式有幾個(gè)弊端:
這樣開發(fā)模式的優(yōu)勢:
業(yè)務(wù)代碼集中在業(yè)務(wù)層 service,專注于業(yè)務(wù)對象 bo 的封裝以及業(yè)務(wù)對象給展示層 vo的轉(zhuǎn)換,封裝復(fù)用邏輯,可以減少大量重復(fù)的代碼,后期維護(hù)便捷的多。
數(shù)據(jù)庫改動(dòng)只設(shè)計(jì)dao層,快速響應(yīng)各個(gè)業(yè)務(wù)。
業(yè)務(wù)代碼如何拒絕 all in one
以上的controller代碼最突出的缺點(diǎn)就是代碼完全無法復(fù)用,完全沒有使用到面向?qū)ο蠓庋b,集成,多態(tài)的特性。業(yè)務(wù)開發(fā)中,一般都是權(quán)限校驗(yàn),參數(shù)校驗(yàn),業(yè)務(wù)判斷,業(yè)務(wù)對象轉(zhuǎn)換數(shù)據(jù)庫操作。
我的做法是業(yè)務(wù)抽象,把公共代碼進(jìn)行抽取,通過配置的形式的方式調(diào)用,使業(yè)務(wù)代碼可以以可插拔的方式選擇指定的權(quán)限校驗(yàn),參數(shù)校驗(yàn)。簡單來說,就是善用AOP面向切面編程的思想,示例如下:
使用aop對權(quán)限校驗(yàn)邏輯進(jìn)行抽取,能夠通過注解的方式指定哪些controller需要進(jìn)行權(quán)限校驗(yàn)。對用戶進(jìn)行數(shù)據(jù)過濾時(shí),使用controller的攔截器獲取該用戶擁有的各類權(quán)限,并把用戶數(shù)據(jù)保存在上下文threadloal中,并且通過配置對指定url進(jìn)行攔截。在業(yè)務(wù)層,從上下文拿到用戶權(quán)限數(shù)據(jù)做各類數(shù)據(jù)業(yè)務(wù)過濾,通過aop實(shí)現(xiàn)各類攔截業(yè)務(wù)的指定調(diào)用。
使用java validtion對通用的字段,例如電話號碼,身份證,進(jìn)行擴(kuò)展,詳細(xì)可以參考,如何使用validation校驗(yàn)參數(shù)?,在項(xiàng)目中其他類似校驗(yàn)進(jìn)行復(fù)用。
業(yè)務(wù)判斷:使用設(shè)計(jì)模式對不同類型的業(yè)務(wù)開發(fā)進(jìn)行封裝,集成,多態(tài)擴(kuò)展;這樣在后期的擴(kuò)展中可以基于開發(fā)封閉原則,針對新的業(yè)務(wù)擴(kuò)展子類即可。
業(yè)務(wù)開發(fā)過程中,依照阿里巴巴研發(fā)規(guī)范的要求,存在DO(數(shù)據(jù)庫表結(jié)構(gòu)一致的對象),BO(業(yè)務(wù)對象),DTO(數(shù)據(jù)傳輸對象),VO(顯示層對象),Query(查詢對象)。
使用MapStruct,可以靈活的控制的不同屬性值之間的轉(zhuǎn)換規(guī)格,比org.springframework.beans.BeanUtils.copyProperties()方法更加靈活。
例如,公共字段,生成日期,創(chuàng)建人,修改時(shí)間,修改人使用插件的形式進(jìn)行封裝,在mybatis-plus中使用MetaObjectHandler,在執(zhí)行sql之前完成統(tǒng)一字段值的填充。
項(xiàng)目如何做好代碼注釋?
在業(yè)務(wù)中特別是狀態(tài)的值,在對外發(fā)布api的vo對象中,加上狀態(tài)枚舉值的注釋,并且使用@link 注解,可以直接連接到枚舉類,讓開發(fā)者一目了然。
Dao是封裝數(shù)據(jù)庫層操作的,寫好了就基本不修改了,所以在封裝的過程中注意必須提供最起碼的增刪查改方式,而且查比較重要,一般會提供分頁查詢
Service層是最繁瑣的一層,也是最重要的一層,一切業(yè)務(wù)的復(fù)雜處理都在這層完成,你的web層只是負(fù)責(zé)傳遞一些數(shù)據(jù)進(jìn)去接受返回的結(jié)果和選擇跳轉(zhuǎn)頁面而已