一、SSH架構(gòu)最基本的分層方式:
modle層:就是對應(yīng)的數(shù)據(jù)庫表的實(shí)體類,即將現(xiàn)實(shí)對象抽象成類。
Dao層:是使用了Hibernate連接數(shù)據(jù)庫、操作數(shù)據(jù)庫(增刪改查)和model層。
Service層:引用對應(yīng)的Dao數(shù)據(jù)庫操作,在這里可以編寫自己需要的代碼(比如簡單的判斷)。
Action層:引用對應(yīng)的Service層,在這里結(jié)合Struts的配置文件,跳轉(zhuǎn)到指定的頁面,當(dāng)然也能接受頁面?zhèn)鬟f的請求數(shù)據(jù),也可以做些計(jì)算處理。
以上的Hibernate,Struts,都需要注入到Spring的配置文件中,Spring把這些聯(lián)系起來,成為一個(gè)整體。
一般java都是三層架構(gòu):數(shù)據(jù)訪問層(dao)、 業(yè)務(wù)邏輯層(biz 或者services)、 界面層(ui)
action 是業(yè)務(wù)層的一部分,是一個(gè)管理器(總開關(guān))(作用是取調(diào)轉(zhuǎn))(取出前臺(tái)界面的數(shù)據(jù),調(diào)用service方法,轉(zhuǎn)發(fā)到下一個(gè)action或者頁面) model模型層:一般是實(shí)體對象(把現(xiàn)實(shí)的的事物變成java中的對象)作用是一暫時(shí)存儲(chǔ)數(shù)據(jù)方便持久化(存入數(shù)據(jù)庫或者寫入文件)二是作為類封裝一些數(shù)據(jù)來在不同的層以及各種java對象中使用。
dao是數(shù)據(jù)訪問層 就是用來訪問數(shù)據(jù)庫實(shí)現(xiàn)數(shù)據(jù)的持久化(把內(nèi)存中的數(shù)據(jù)永久保存到硬盤中)
Modle 是模型,存放你的實(shí)體類
Dao主要做數(shù)據(jù)庫的交互工作(hibernate)
Service 做相應(yīng)的業(yè)務(wù)邏輯處理
Action是一個(gè)控制器(structs)
java中dao層和service層的區(qū)別是什么?
service是業(yè)務(wù)層,dao是數(shù)據(jù)訪問層。
這個(gè)問題我曾經(jīng)也有過,記得以前剛學(xué)編程的時(shí)候,都是在service里直接調(diào)用dao,service里面就new一個(gè)dao類對象,調(diào)用,其他有意義的事沒做,也不明白有這個(gè)有什么用,參加工作久了以后就會(huì)知道,業(yè)務(wù)才是工作中的重中之重。
我們都知道,標(biāo)準(zhǔn)主流現(xiàn)在的編程方式都是采用MVC綜合設(shè)計(jì)模式,MVC本身不屬于設(shè)計(jì)模式的一種,它描述的是一種結(jié)構(gòu),最終目的達(dá)到解耦,解耦說的意思是你更改某一層代碼,不會(huì)影響我其他層代碼,
如果你會(huì)像spring這樣的框架,你會(huì)了解面向接口編程,表示層調(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的意義。
在各層中不要含有其他層的new的具體對象,最多只能有引用。
接下來說你感覺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ù)里寫。
只是剛開始寫的代碼都是有個(gè)請求,就去數(shù)據(jù)庫取,業(yè)務(wù)幾乎沒有,這是不對的。
二、Action層, Service層 ,modle層 和 Dao層的功能區(qū)分
Action主要的功能就是組織service的,比如你要做權(quán)限驗(yàn)證,那么請求會(huì)被Action獲取,那么如何驗(yàn)證呢?Action可不管他要問service該怎么辦。當(dāng)?shù)玫絪ervice返回的結(jié)果后根據(jù)結(jié)果判斷下一跳是哪里(如果驗(yàn)證用戶存在且密碼正確則跳轉(zhuǎn)到登錄成功的頁面,反之則回跳到登錄頁面)
現(xiàn)在輪到service了,service是管理業(yè)務(wù)的,延續(xù)上面的例子的話,action問這個(gè)用戶是否合法有效的時(shí)候sevice就去調(diào)用dao層,看dao能不能找到相應(yīng)的記錄,當(dāng)業(yè)務(wù)受到dao的結(jié)果后就根據(jù)得到的記錄回答action的問題“用戶是否合法有效”
最后就是dao了,作為工作于最“基層”的部分,dao層只去實(shí)現(xiàn)增刪查改,甚至這些增刪查改之間有什么關(guān)系?dao一概不問,愛誰是誰。dao很倔強(qiáng),它只保證和數(shù)據(jù)庫的關(guān)系良好。
歸納一下,Action就是管理業(yè)務(wù)(servcie)調(diào)度和管理跳轉(zhuǎn)的。service是管理具體的功能的,這個(gè)很容易和Action混淆,你可以這樣理解,Action只負(fù)責(zé)管理,而service負(fù)責(zé)實(shí)施,dao只完成增刪查改,當(dāng)然你可以1-n,n-n,1-1關(guān)聯(lián),模糊 、動(dòng)態(tài) 、子查詢都可以。但是無論多么復(fù)雜的dao,它只是封裝增刪查改。至于增刪查改如何實(shí)現(xiàn)一個(gè)功能,dao層是不管的。
總結(jié)這三者,可以舉個(gè)例子,action像是服務(wù)員,顧客點(diǎn)什么菜,菜上給幾號桌,都是action的職責(zé);sevice是廚師,action送來的菜單上的菜全是service做的;dao是廚房的小工,和原材料打交道的事情全是它管。所以小工(dao)的工作是要滿足廚師(service)的要求,廚師要滿足服務(wù)員(action)轉(zhuǎn)達(dá)的客戶(頁面用戶)的要求,服務(wù)員自然就是為客戶服務(wù)嘍。
首先這是現(xiàn)在SSH架構(gòu)最基本的分層方式。modle層就是對應(yīng)的數(shù)據(jù)庫表的實(shí)體類。Dao層是使用了Hibernate連接數(shù)據(jù)庫、操作數(shù)據(jù)庫(增刪改查)。Service層:引用對應(yīng)的Dao數(shù)據(jù)庫操作,在這里可以編寫自己需要的代碼(比如簡單的判斷)。Action層:引用對應(yīng)的Service層,在這里結(jié)合Struts的配置文件,跳轉(zhuǎn)到指定的頁面,當(dāng)然也能接受頁面?zhèn)鬟f的請求數(shù)據(jù),也可以做些計(jì)算處理。以上的Hibernate,Struts,都需要注入到Spring的配置文件中,Spring把這些聯(lián)系起來,成為一個(gè)整體。
簡單的說:
struts 控制用的
hibernate 操作數(shù)據(jù)庫的
spring 用解耦的
詳細(xì)的說:
STRUTS 在 SSH 框架中起控制的作用 , 其核心是 Controller, 即 ActionServlet, 而 ActionServlet 的核心就是 Struts-confi g.xml. 主要控制邏輯關(guān)系的處理 .
hibernate 是數(shù)據(jù)持久化層 , 是一種新的對象、關(guān)系的映射工具 , 提供了從 Java 類到數(shù)據(jù)表的映射,也提供了數(shù)據(jù)查詢和恢復(fù)等機(jī)制 , 大大減少數(shù)據(jù)訪問的復(fù)雜度。把對數(shù)據(jù)庫的直接操作 , 轉(zhuǎn)換為對持久對象的操作 .
SPRING 是一個(gè)輕量級的控制反轉(zhuǎn) (IoC) 和面向切面 (AOP) 的容器框架 , 面向接口的編程 , 由容器控制程序之間的(依賴)關(guān)系,而非傳統(tǒng)實(shí)現(xiàn)中,由程序代碼直接操控。這也就是所謂 “ 控制反轉(zhuǎn) ” 的概念所在:(依賴)控制權(quán)由應(yīng)用代碼中轉(zhuǎn)到了外部容器,控制權(quán)的轉(zhuǎn)移,是所謂反轉(zhuǎn)。依賴注入,即組件之間的依賴關(guān)系由容器在運(yùn)行期決定,形象的來說,即由容器動(dòng)態(tài)的將某種依賴關(guān)系注入到組件之中起到的主要作用是解耦
Struts 、 spring 、 Hibernate 在各層的作用
1 ) struts 負(fù)責(zé) web 層 .
ActionFormBean 接收網(wǎng)頁中表單提交的數(shù)據(jù),然后通過 Action 進(jìn)行處理,再 Forward 到對應(yīng)的網(wǎng)頁。
在 struts-config.xml 中定義 <action-mapping>, ActionServlet 會(huì)加載。
2 ) spring 負(fù)責(zé)業(yè)務(wù)層管理,即 Service (或 Manager).
1 . service 為 action 提供統(tǒng)計(jì)的調(diào)用接口,封裝持久層的 DAO.
2 .可以寫一些自己的業(yè)務(wù)方法。
3 .統(tǒng)一的 javabean 管理方法
4 .聲明式事務(wù)管理
- 集成 Hiberante
3 ) Hiberante ,負(fù)責(zé)持久化層,完成數(shù)據(jù)庫的 crud 操作
hibernate 為持久層,提供 OR/Mapping 。
它有一組 .hbm.xml 文件和 POJO, 是跟數(shù)據(jù)庫中的表相對應(yīng)的。然后定義 DAO ,這些是跟數(shù)據(jù)庫打交道的類,它們會(huì)使用 PO 。
在 struts+spring+hibernate 的系統(tǒng)中,
對象的調(diào)用流程是: jsp-> Action - > Service ->DAO ->Hibernate 。
數(shù)據(jù)的流向是 ActionFormBean 接受用戶的數(shù)據(jù), Action 將數(shù)據(jù)從 ActionFromBean 中取出,封裝成 VO 或 PO,再調(diào)用業(yè)務(wù)層的 Bean 類,完成各種業(yè)務(wù)處理后再 forward 。而業(yè)務(wù)層 Bean 收到這個(gè) PO 對象之后,會(huì)調(diào)用 DAO 接口方法,進(jìn)行持久化操作。
SSH框架都是取其優(yōu)點(diǎn)的:
Hibernian 的最大好處就是根據(jù)數(shù)據(jù)庫的表反向生成實(shí)體類,并且還有關(guān)系在里面,還有就是它的對數(shù)據(jù)的操作也很方便。
Spring 我理解的就是創(chuàng)建對象工廠,省去了在類里面new 對象的過程,把這個(gè)調(diào)用與被調(diào)用的關(guān)系直接展示到了配置文件里,做任何操作都變簡單了。
項(xiàng)目實(shí)現(xiàn)舉例
程序框架搭好,各種jar包導(dǎo)好后,開工了
就拿注冊功能來說 頁面只有兩個(gè)文本框 一個(gè)用戶名(uname) 一個(gè)密碼(pwd)
首先是action層: 它是負(fù)責(zé)在頁面和程序之間傳輸數(shù)據(jù)的,還有作用是做頁面跳轉(zhuǎn)。頁面由用戶填寫表單數(shù)據(jù),點(diǎn)擊提交按鈕,頁面的表單數(shù)據(jù)由Hibernian自動(dòng)封裝到該頁面表單所對應(yīng)的ActionFrom(ActionFrom跟實(shí)體類不是一個(gè)東西,ActionFrom是頁面有什么值,我類里就寫什么屬性,是封裝表單數(shù)據(jù)用的。而實(shí)體類是完全按照數(shù)據(jù)庫的字段生成的,實(shí)體類可以當(dāng)做ActionFrom用,但ActionFrom絕對不可以當(dāng)做實(shí)體類用),這樣表單數(shù)據(jù)就以ActionFrom對象的形式在Action的點(diǎn)擊提交按鈕執(zhí)行的那個(gè)方法里存在了,這個(gè)時(shí)候你需要的就是把表單數(shù)據(jù)存入數(shù)據(jù)庫中,但如果數(shù)據(jù)庫里并非只有頁面上的uname和pwd兩個(gè)字段,還有其他字段比如用戶狀態(tài),那你就需要另行在程序里給該屬性賦值了,否則會(huì)報(bào)非空錯(cuò)誤,這里的例子,頁面只有兩個(gè)文本框,數(shù)據(jù)庫也只有這兩個(gè)字段,就不必考慮那么多了,到這一步,action的功能告一段落了,接著是把數(shù)據(jù)傳入services層。
Biz層(業(yè)務(wù)邏輯層)/service層:
它負(fù)責(zé)的是對數(shù)據(jù)的處理,比如網(wǎng)站功能是點(diǎn)卡銷售,你就需要在這個(gè)層里對點(diǎn)卡的打折啊其他的數(shù)學(xué)問題做操作了,在這個(gè)例子里,此層只做單純的數(shù)據(jù)傳遞作用,而后又到了DAO層。
Dao層(數(shù)據(jù)庫操作層):它負(fù)責(zé)對數(shù)據(jù)向數(shù)據(jù)庫增刪改查的操作。
以上例子,不使用spring的話,每個(gè)層之間的數(shù)據(jù)傳遞你都需要new一個(gè)調(diào)用該層數(shù)據(jù)的類的實(shí)例,而使用了spring的話,你需要做的就是把Dao 層和services層的每個(gè)類都寫一個(gè)接口類,接口類里寫實(shí)現(xiàn)類的方法,在調(diào)用的時(shí)候不new 對象,直接用對象點(diǎn)(.)方法就可以,別忘了對每個(gè)對象加set/get方法。
業(yè)務(wù)邏輯層)/service層例子:
private saveMyScheduleDaoImpl smsDI; //類里定義寫接口(saveMyScheduleDaoImpl ),不要寫實(shí)現(xiàn)類,并且不new
set/get方法略·········
public List saveMySchedule(Schedule s)
{
return smsDI.saveMySchedule(s); //因?yàn)槭墙涌诘膶?shí)例,所以要求該接口里必須寫上實(shí)現(xiàn)類的所有方法,這樣才能點(diǎn)(.)
}
這里只簡單寫了一個(gè)services層的。
以上流程只是從頁面獲取值存入數(shù)據(jù)庫,是單向的Action層->services層->Dao層的數(shù)據(jù)傳遞,Dao層->services層->Action層的數(shù)據(jù)傳遞和我剛剛將的一樣,就是反過來了。
到這一步的總結(jié):
Dao層寫接口并且接口里寫實(shí)現(xiàn)類的所有方法。
Services層寫接口并且接口里寫實(shí)現(xiàn)類的所有方法。調(diào)用Dao層方法只定義Dao層需要調(diào)用方法所屬的類的接口,而后添加get/set方法,再用該接口的沒有new的實(shí)例點(diǎn)(.)方法。
Action層同Biz層。
下面就是強(qiáng)大的spring的工作了-------依賴注入
所有改寫的死東西都寫完了,我們就差在配置文件里依賴注入了
找到spring的配置文件,先注Dao層,這個(gè)時(shí)候一定要注意一點(diǎn),就是依賴注入的時(shí)候注的必須是實(shí)體類??! 而不是接口??! 這是一種良好的變成習(xí)慣。
Dao層的依賴注入里綁定的是你在往工程加Spring的時(shí)候讓你填寫SessionFactory的那個(gè)值,配置文件上面應(yīng)該會(huì)有這個(gè)bean的。
然后是Services層的依賴注入,同樣也是注實(shí)體類,根據(jù)我這個(gè)例子里面會(huì)有smsDI需要綁定,這個(gè)時(shí)候填寫你注的Dao層的相對應(yīng)的類的名字就行。
然后是Action層的依賴注入,大體同Services層一樣。
依賴注入完畢后,你就可以配置了。
原文鏈接:https://blog.csdn.net/david_snjly/java/article/details/45568573