實習了三個月,對着SSH有着必定的認識了,就以自已認識的大概思路寫一篇文章吧,留給之後的自已,也懇請各位博友們若是看到個人認識有過錯的地方能幫我指正過來!html
在寫正文以前,先說說我這段時間學習SSH所用到的資料吧!因此在我下面所認識中所說的話若是有跟我學習資料中說的差很少的或者如出一轍的,還懇請各位的原諒,畢竟個人知識就是從大家那兒學的。剛接觸SSH是照着一位博友的博文來搭建的(Eclipse搭建SSH(Struts2+Spring3+Hibernate3)框架項目教程),在搭建的過程當中出錯了好多錯誤,當時我還一邊在看尚學堂馬士兵的視頻來搭建的(發現照着網上的搭建時通常會由於你下載的spring、struts、hibernate等版本的不一樣而出現錯誤,這咱們搭建時仍是得參考咱們所下載裏面的技術文檔,例如我下載的hibernate爲hibernate-distribution-3.6.10.Final,在這裏面有hibernate-distribution-3.6.10.Final\documentation\manual\zh-CN\html\index.html的技術文檔,固然,我打開的是中文版的,裏面還有別的語言版本的)。java
在個人框架搭建好後,我便深刻的去理解。這過程當中我主要有用到兩份資料,一份是一博友zs234的博客,這博友寫的真心不錯,至少對於我來講,感受簡明易懂。還有另外一份資料就是李剛的書了(JavaEE企業應用實戰-Struts2Spring3Hibernate整合開發第3版,這書我網上找了份有書籤的pdf,又去到噹噹網買了本,感受不錯。這pdf我上傳到了我所在的QQ技術交流羣上300638185,也上傳了份在百度雲上面,有須要的博友能夠點擊此下載)web
先從struts2提及(說到struts1與struts2,我以爲主要的一個不一樣就是struts2有着線程安全吧,而struts1的線程不安全,由於它多用戶共享同一線程了),struts2是一個經典的繼Model1和Model2後的MVC框架,所謂的MVC,就是Model+View+Control.ajax
Model爲邏輯層,負責邏輯業務(不包括數據業務,至少我在網上看到的都是這樣,但我師兄跟我說查詢語句能夠寫到manager(有的資料也叫service,至少我第一次搭建的框架就叫service)裏面,當時我就暈了,manager不是MVC裏面的M嗎?怎麼能夠寫在裏面了,下面講ioc時我會說另外一點爲何我不肯意丟掉dao層,到如今我仍是喜歡把查詢語句寫在dao層裏面,manager就作邏輯處理,固然我也有了解到查詢語句能夠寫到新建的一個配置文件裏面,惋惜我只瞭解了一下,還沒仔細去了解這個)。spring
View爲顯示層,主要組件有jsp頁面與一些jsp頁面的小插件。數據庫
Control爲控制器,主要體如今action上面,學習action,會學習到5個名詞,分別爲:actionServlet、actionMapping、actionForm、action、actionForward,這5個名詞能夠構成一個小過程:客戶端發送一個請求給服務器,服務器web.xml接收並分配給相應的servlet,這時的servlet就是struts.xml裏面的actionServlet,actionServlet根據URL來截取配置信息,這些配置信息在actionMapping裏面,而後生成相應的actionForm與action,actionForm裏面放置的用戶的請求信息,action實行控制,裏面有個execute()方法,能夠實行相應的操做,此時也能夠進入邏輯業務(也就是調用Model層),最後以返回的參數實行actionForward來生成新的jsp界面.json
此時也能夠不生成新的jsp界面,這種狀況是我在作ajax異步時發現的,此時struts.xml裏面的代碼以下安全
<action name="loginPro" class="org.crazyit.app.action.LoginAction"> <result name="success" type="stream"> <!-- 指定下載文件的文件類型 --> <param name="contentType">text/html</param> <!-- 指定由getResult()方法返回輸出結果的InputStream --> <param name="inputName">result</param> </result> </action>
此時經過使用stream類型的Result,Strut2能夠無需jsp視圖界面,直接在Action向瀏覽者生成指定的響應。服務器
更深層不生成新的jsp界面的一個就是還利用了json,此時得引入struts2-json-plugin-2.3.15.1.jar包,也對struts.xml文件有着必定的修改,以下:session
<constant name="struts.i18n.encoding" value="UTF-8"></constant> <include file="struts-plugin.xml" /> <package name="ynwi" extends="json-default"> <action name="s2AA" class="s2AAa"> <result type="json"> <!-- 爲該Result指定參數 --> <param name="noCache">true</param> <param name="contentType">text/html</param> </result> </action>
上面說到action的5個名詞時小談了下SSH中一小部分的運行,下面我接着說,request有兩種傳值(就是actionForm)方式(在java文件裏面以setter來獲取這些信息),一種是get傳值,這種方式傳值時特色是會在地址欄後面加上你要傳這值,這容易看出這種傳值方式不安全與傳的值量不大,另外一種是form傳值,是比較經常使用的傳值方式,就是生成表格來存取數據,能夠存儲的數據量也比較大。
當咱們按jsp界面的按鈕時,咱們便直接來到struts.xml裏面吧,咱們根據action中的name來對應咱們應該響應的action事件,class爲指定的action的java類,若是此時不是指定java類,而是以一個名字指定到applicationContext.xml文件裏面的話,這時就是說明進入了邏輯層了,此時action的java類爲applicationContext.xml文件裏面以那名字命名的bean的class,這個過程呢,咱們叫他作「讓spring來管理控制器」,此時主要內容以下:
struts.xml裏面:
<action name="Login" class="userLogin"> <result name="admin">/index.jsp</result> <result name="customer">/Success_Customer.jsp</result> <result name="error">/Fail.jsp</result> </action>
applicationContext.xml裏面:
<bean id="userLogin" class="com.slt.ssh.action.userLoginAction"> <property name="userManager"> <ref bean="userManager"></ref> </property> </bean>
另外還有一種方式叫作「自動裝配」,這個先上代碼我再說一下
struts.xml裏面:
<action name="loginPro" class="org.crazyit.app.action.LoginAction"> <!-- 爲兩個邏輯視圖配置視圖頁面 --> <result name="error">/WEB-INF/content/error.jsp</result> <result name="success">/WEB-INF/content/welcome.jsp</result> </action>
applicationContext.xml裏面:
<bean id="ms" class="org.crazyit.app.service.impl.MyServiceImpl"/>
LoginAction.java裏面:
private MyService ms; public void setMs(MyService ms) { this.ms = ms; }
自動裝配就是以applicationContext.xml來自動找java文件裏面的setMs方法。
如今,咱們已經開始慢慢進入spring了,applicationContext.xml就是spring裏面的知識點。@左瀟龍博友說得好:「更準確的能夠說spring是一個應用平臺,能夠這麼理解spring就是操做系統,hibernate、struts都是網卡、顯卡等插件,可插拔。操做系統管理着硬件,spring管理着這些hibernate持久層的ORM框架或者strutsMVC等框架。」對於spring,我認爲最主要的知識就是AOP與IoC了,AOP簡單理解就是給程度增長統一的功能的技術,是在不修改源代碼的狀況下,在經過編譯或運行期動態代碼的狀況下。IoC(控制反轉)簡單理解就是把調用者的控制權交給第三方。IoC裏面有許多概念:依賴,依賴倒置,依賴注入。
依賴:.java文件中若是A類有在本身的方法中實例化B類,那麼就說A依賴於B。
依賴倒置:進行解耦,主要有兩個原則
一、上級不能依賴於下級,能夠共同依賴於另外一抽象類(這裏就是引進了接口,接口屬於抽象類)。
二、抽象類不能依賴於實體類。
依賴注入:就是在spring容器中實例化的內容注入到.java文件中。依賴注入裏面有兩種,一種是設值注入,另外一種是構造注入。咱們用得多的是設值注入。
設值注入,先上主要代碼再說明:
Chinese.java
private Axe axe; //設值注入所需的setter方法 public void setAxe(Axe axe) { this.axe = axe; }
applicationContext.xml
<bean id="chinese" class="org.crazyit.app.service.impl.Chinese"> <!-- 將stoneAxe注入給axe屬性 --> <property name="axe" ref="stoneAxe"/> </bean> <!-- 配置stoneAxe實例,其實現類是StoneAxe --> <bean id="stoneAxe" class="org.crazyit.app.service.impl.StoneAxe"/>
咱們能夠看到xml文件時面property中的name爲axe與java文件裏面的setAxe相對應,這時也就是說咱們把ref後面的stoneAxe注入給了java文件了,也就是說此時咱們作的是在Chinese.java對StoneAxe類進行實例化,這樣達到了鬆耦合的原理。
構造注入,這個就簡單地上下代碼吧。
Chinese.java
//構造注入所需的帶參數的構造器 public Chinese(Axe axe) { this.axe = axe; }
applicationContext.xml
<bean id="chinese" class="org.crazyit.app.service.impl.Chinese"> <!-- 使用構造注入,爲chinese實例注入steelAxe實例 --> <constructor-arg ref="steelAxe"/> </bean>
<bean id="steelAxe" class="org.crazyit.app.service.impl.SteelAxe"/>
上面所說到的師兄叫我把查詢語句寫在manager裏面,我不肯意的緣由也有個感受就是總以爲這樣作不符合ioc,就是我會把applicationContext.xml當作是第三方,manager當作是調用者,dao當作是實現層,ioc不就是把實現層的控制權給第三方來控制嗎?若是沒了dao這一層,那這不就是不符合ioc了嗎?後來慢慢以爲可不能夠這樣子看呢,就是把action看到是調用者,把manager當作是實現層,好像這樣子想還真感受有點道理,就是網上看了別人的都不是這樣子的,奇怪奇怪,到如今仍是感受怪怪的。
下面咱們回到從struts進入到spring後,一開始的進入是以「讓spring管理控制器」的方式進入的,進入後都是經過ref來鏈接用到了多個bean,這樣子就會有可能進入到邏輯層(manager),數據接口層(dao),在spring整合了hibernate與struts後,咱們也是把鏈接數據源寫在了applicationContext.xml文件裏面,例如factory,session等。
另外咱們要用到spring中的bean,也能夠用ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext來獲取bean.
在邏輯業務的控制下,咱們進入了hibernate,hibernate就是以數據庫相關連,對於hibernate的一對一,一對多等等的關聯映射,我真心還沒搞懂,對於註釋,我也就懂了一點而已,至少還知道.hbm.xml文件主要用來對應數據庫表裏面的字節吧。不過hibernate我仍是懂得查詢是要創建工廠sessionfactory生產會議session等,在查詢後還要關閉這會session什麼的,可是咱們如今有個getHibernateTemplate()函數,這是已經封裝好的函數,咱們直接用就好了,省了不少步驟。通常咱們查詢出來的結果以List來返回,固然也能夠用別的東東來返回。
返回到action的java文件後,再傳值給struts.xml文件,這時struts.xml會根據傳回來的值生成一個新的頁面。