Spring更新到3.0之后,其MVC框架加入了一個非常不錯的東西——那就是REST。它的開放式特性,與Spring的無縫集成,以及Spring框架的優(yōu)秀表現(xiàn),使得現(xiàn)在很多公司將其作為新的系統(tǒng)開發(fā)框架。大象根據(jù)實際的項目經(jīng)驗,以之前SSH2例子為基礎,對其進行一次大改造,詳細的為大家講解如何實現(xiàn)SSM3全注解式的開發(fā)。
這次大象將采取兩種構建方式,一是很多人喜歡用的MyEclipse,另一個,則是用Eclipse+Maven。這一篇,將主要講解開發(fā)環(huán)境設置與Maven構建方式。
1、
開發(fā)環(huán)境 Eclipse3.2.1 MyEclipse5.1.0 Eclipse-JEE-HELIOS-SR2 Maven3.0.1 m2eclipse0.12.1.20110112-1712
Tomcat6.0.10 maven-jetty-plugin6.1.26
MySQL5.0.27 Navicat Lite for MySQL 8.1.20
每個人的開發(fā)環(huán)境可能會有差異,但有一點我需要說明的是,JDK的版本不得低于1.5,因為用到了很多1.5版才支持的新特性。Tomcat、Jetty、Maven和MySQL請不要低于我所用的版本,因為我沒在其它的版本上進行測試。Navicat則是MySQL數(shù)據(jù)庫的圖形化操作工具。接下來我將介紹如何在Eclipse3.6中,使用m2eclipse插件構建web應用及測試開發(fā)環(huán)境。
Maven的安裝很簡單,只需要解壓即可,請設置PATH變量,這樣可以使用命令行進行操作,然后就要在%MAVEN_HOME%\conf目錄下,對settings.xml作下修改
這就是設置本地倉庫,目錄可以根據(jù)自己的實際情況更改,不過請使用"/"正斜杠,因為我在實際使用中,發(fā)現(xiàn)反斜杠有時候獲取不到資源。對于個人使用,設置好這個就OK了,至于Nexus配置不在本文討論范圍內(nèi),大家如有興趣可以去看看juven xu的博客,他是目前公認的Maven專家。
選擇Help->Install New Software...在彈出的窗口中,點擊Add...又會彈出一個小窗口,輸入m2eclipse的安裝地址,如下圖所示:
輸入完成后,點擊OK,這時Eclipse就開始查找這個插件了,請耐心等一會。
插件找到后,請勾選要安裝的內(nèi)容,接下來就是一般的安裝流程了,此處省略500字。安裝完成請重新啟動Eclipse,然后再對這個插件進行一番設置。
進入Perferences,選擇Maven,去掉Download repository index updates on startup前的勾,默認情況是會在每次啟動Eclipse的時候自動去Maven中央倉庫下載索引,這無疑是非常不好的,要知道Maven中央倉庫所包含的jar資源非常龐大,而且每天都會有很多新的項目上傳,弄不好Eclipse還沒開始用,就被這些東西搞掛掉了。 接下來選擇Installations將這個插件自帶的Maven換成之前安裝的Maven,這樣就保證了版本的一致性。
設置好這個之后,再點擊User Settings,用本機maven的settings.xml替換默認的配置文件,因為默認的設置是會將本地倉庫放到系統(tǒng)盤符\Documents and Settings\用戶目錄\.m2\repository這個目錄下面。
大家可以看到,用maven中的配置文件替換后,下面的Local Repository自動變更為settings.xml中的設置。
做完這些,我們就可以開始創(chuàng)建Maven工程了。選擇New->other...->Maven->Maven Project,然后選擇下一步
請設置工作空間路徑,大象的默認工作空間放在eclipse的根目錄下面,這里的Location顯示的應該為空,為了進行說明,特將路徑顯示出來。確定沒問題后,Next>
這個列表顯示的就是maven支持的所有項目創(chuàng)建類型,我們是開發(fā)web應用,所以請選擇maven-archetype-webapp
最后一步輸入我們要創(chuàng)建的項目,在Maven世界中,使用坐標來唯一標識一個構件,可以理解為項目,資源等等。Group Id表示當前項目所屬的實際項目,Artifact Id定義實際項目中的一個Maven項目,根據(jù)名字就可以看出來,Group Id是一個大范圍,而Artifact Id是一個小范圍。比如大家都很熟悉的spring,就分成了spring-core.jar、spring-beans.jar、spring-context.jar等等。在maven里面,它的Group Id就是org.springframework,而Artifact Id則為spring-core、spring-beans、spring-context。怎么樣?理解了沒有?
到此,項目生成了,請展開src/main,在main目錄下新建一個java文件夾,打開ssm3的項目屬性,選擇Java Build Path->Source->Add Folder...->勾選java,這樣做的目的,就是將src/main/java這個路徑作為源文件的文件夾,這和以往用MyEclipse做開發(fā)的目錄結構是不同的。而maven的規(guī)則也是這樣定義的,假如你不進行這個設置,就算你在main下面創(chuàng)建了java目錄,再添加包或類時,就會有問題,大家試試,看會出現(xiàn)什么錯誤。
運行ssm3
接下來,在pom.xml里面加入maven-jetty-plugin插件,默認生成的配置都可以去掉,整個pom就只有下圖所示的配置。 打開Run Configurations,這有多種方式打開,可以從菜單Run里面選,也可以從工具欄選擇,還可以在項目點擊右鍵選擇。
在彈出的窗口,Maven Build里面設置運行參數(shù),點擊Browse Workspace...會彈出下圖那個小窗口,設定Base directory,加入jetty:run,點擊Run,啟動jetty
在瀏覽器中輸入http://localhost:8080/ssm3會顯示Hello World!,調(diào)用的是ssm3/main/webapp/index.jsp,大象加了點內(nèi)容,結果就是這樣的
到這里,關于在Eclipse里搭建maven環(huán)境,配置,創(chuàng)建,運行,測試就全部講完了,大家動手做做,熟悉一下這種開發(fā)方式,接下來就會在這個骨架上開發(fā)SSM3示例。
在上一篇文章中我詳細的介紹了如何搭建maven環(huán)境以及生成一個maven骨架的web項目,那么這章中我將講述Spring MVC的流程結構,Spring MVC與Struts2的區(qū)別,以及例子中的一些配置文件的分析。
一、Spring MVC 3.0介紹 Spring MVC是一個典型的MVC框架,是Spring內(nèi)置的Web框架,可以作為應用項目的展示層,繼Spring 2.0對Spring MVC進行重大升級后,Spring 2.5又為Spring MVC引入了注解驅(qū)動功能,再到3.0時代,全面支持REST的網(wǎng)絡服務和更容易的網(wǎng)絡編程。這一系列的變革,無疑吸引著我們走進Spring MVC 3.0的世界。
REST功能是Spring MVC 3.0新增的,它通過不帶擴展名的URL來訪問系統(tǒng)資源。REST是把訪問的所有資源看成靜態(tài)的,一個或一組,每個不同的URL地址都是一個靜態(tài)資源。那么Spring MVC 3.0是如何支持REST的呢?簡單的說,它是通過@RequestMapping及@PathVariable注解提供的,在@RequestMapping中指定value與method,就可以處理對應的請求。另外spring mvc框架還做了很多很多工作。
二、Spring MVC流程 大象根據(jù)官方文檔的介紹,以及自己的理解,畫了一個Spring MVC的流程結構圖,大家可以參考下。
1、Spring MVC的核心是DispatcherServlet,當客戶端發(fā)送一個請求時,這個請求經(jīng)過一系列過濾器處理。然后DispatcherServlet會接收到這個請求。
2、DispatcherServlet會從HandlerMapping對象中查找與請求匹配的Controller,并將結果返回給DispatcherServlet。
3、DispatcherServlet將請求轉(zhuǎn)發(fā)給目標Controller,如果定義有攔截器,則會經(jīng)過這些攔截器處理。
4、標Controller處理完成業(yè)務邏輯后,會返回一個結果給DispatcherServlet。
5、DispatcherServlet根據(jù)結果查詢ViewResolver,找到與之對應的視圖對象,同樣將結果返回給DispatcherServlet。
6、DispatcherServlet根據(jù)指定的顯示結果,調(diào)用模板對象渲染view。
7、將view返回給客戶端。
根據(jù)上面的說明,可以很很明顯的看出,Spring MVC的核心是Servlet,并且創(chuàng)建的Controller其實也是一個Servlet。
三、Spring與struts2比較
另一個非常有名的MVC框架是Struts2,Spring MVC的核心是Servlet,而Struts2的核心則是Filter。下表列出Spring MVC與Struts2的主要區(qū)別與比較結果。
通過上面的綜合比較,Spring MVC 3.0的優(yōu)勢要比Struts2大得多,雖然它還有些不足的地方,但隨著后期版本的升級,必然會進行改進,會做的更好。所以采用Spring MVC 3.0作為系統(tǒng)的展示層要比Struts2好。
四、線程安全
由于Spring MVC默認是Singleton的,所以會產(chǎn)生一個潛在的安全隱患。根本核心是instance變量保持狀態(tài)的問題。
這個問題有兩種解決辦法:
a) 在控制器中不使用實例變量
b) 將控制器的作用域從單例改為原型
這兩種做法有好有壞,第一種,需要開發(fā)人員擁有較高的編程水平與思想意識,在編碼過程中力求避免出現(xiàn)這種BUG,而第二種則是容器自動的對每個請求產(chǎn)生一個實例,由JVM進行垃圾回收,因此做到了線程安全。使用第一種方式的好處是實例對象只有一個,所有的請求都調(diào)用該實例對象,速度和性能上要優(yōu)于第二種,不好的地方,就是需要程序員自己去控制實例變量的狀態(tài)保持問題。第二種由于每次請求都創(chuàng)建一個實例,所以會消耗較多的內(nèi)存空間。
五、配置文件
Spring MVC是Spring的一個組成部分,所以配置文件就會變得簡單許多。以下就是本例子中最重要的幾個配置文件。
1、pom.xml
管理項目依賴,編譯,發(fā)布,插件配置等等。所有的依賴包都由配置決定,另外所需依賴包的其它依賴,無需配置,maven會自動獲取并進行管理,這無疑幫我們減少了很多工作量,再也不用為到處找jar包,或版本不一致而頭疼了。
定義依賴版本屬性
Spring依賴,本例是一個很基礎的例子,所以有這些就夠了,以后有擴展再增加。
MyBatis依賴,iBatis從3.0版之后就改名為MyBatis。這個例子,大象沒有使用Hibernate,而是采用更輕量級的MyBatis來作為持久層框架,使用很簡單,也很靈活。另外,本例還用到了一個mybatis-spring插件,這是因為spring 3.0.5僅支持ibatis 2.0,所以需要這個插件來處理底層數(shù)據(jù)源等工作。
下面是其它一些必須的依賴,值得說明的就是,因為在本例中,大象對Service還是用的類,沒有進行基于接口的實現(xiàn)方式,所以需要cglib這個依賴。另外,頁面使用html作為展示層,使用freemarker標簽處理動態(tài)數(shù)據(jù)。
2、web.xml 與ssh2的web.xml主要的區(qū)別就是替換Struts2的啟動配置,改為Spring MVC的設置,配置如下:
servlet-context.xml包含容器啟動時,所要執(zhí)行的內(nèi)容,而service-context.xml則是接下來由spring上下文監(jiān)聽器對其進行掃描執(zhí)行。這兩個配置文件可以合并成一個,大象為了便于管理,并且為了使用spring上下文,寫成了兩個文件。如果我們不指定init-param配置,默認的,在服務器啟動時,會在WEB-INF目錄下查找命名規(guī)則為<servlet-name>-servlet.xml的文件,對應到這里就是ssm3-servlet.xml文件,大象統(tǒng)一將所有文件都放在了classpath下面。
3、servlet-context.xml
Spring MVC啟動時的配置文件,包含組件掃描、url映射以及設置freemarker參數(shù),讓spring不掃描帶有@Service注解的類。為什么要這樣設置?因為servlet-context.xml與service-context.xml不是同時加載,如果不進行這樣的設置,那么,spring就會將所有帶@Service注解的類都掃描到容器中,等到加載service-context.xml的時候,會因為容器已經(jīng)存在Service類,使得cglib將不對Service進行代理,直接導致的結果就是在service-context中的事務配置不起作用,發(fā)生異常時,無法對數(shù)據(jù)進行回滾。另外能夠?qū)?/span>REST URL解析為請求映射的是DefaultAnnotationHandlerMapping這個類,它在啟動時,對Controller中所有標注了@RequestMapping注解的方法,都放到了一個HandlerMapping對象中,當有請求時,就在這個對象中進行查找是否有與之匹配路徑的處理方法,有則執(zhí)行,沒有就會輸出一個Not Page Found警告信息。
展示層使用freemarker模板引擎,為了便于編輯,大象在這里使用html作為展示頁。Spring框架對freemarker進行了集成與封裝,配置起來非常簡單。主要是定義FreeMarker視圖解析器與屬性配置,網(wǎng)上有很多關于這些屬性含義的介紹,大象就不在這里啰嗦了,后面講到Spring MVC的時候會結合代碼來進行說明。Spring MVC支持多種類型的視圖文件。如:jsp、freemarker、velocity、tiles、jasperreports等。
4、service-context.xml
與ssh2里面的application.xml區(qū)別不大,主要是將hibernate那部分改為mybatis,還要將MybatisDao基類配置進來,以便Service類可以用注解的方式引入,然后就是掃描包路徑,不掃描帶有@Controller注解的類。因為這些類已經(jīng)隨容器啟動時,在servlet-context中掃描過一遍了。
5、mybatis-config.xml
mybatis的主配置,里面包含了POJO的映射文件,這里了解一下就行,后面的章節(jié)會對這些進行說明,熟悉ibatis的朋友就很簡單了,可以直接跳過。
到此,關于配置文件的說明就講完了,因為這個SSM3的例子采用maven來構建,與之前的SSH2不一樣,大象對配置文件進行了簡要的說明,使用maven的好處,大家應該看出來了,它對于開發(fā)構建來說顯得簡單一些,可以使你不需要到處去找jar包,也不用你去擔心版本不一致的問題,另外,對于依賴的jar包,它還能自動去查找它自己的依賴,這可以減少我們很多不必要的重復勞動。下一章,我將分析下本例的層次結構與MyBatis的簡單運用。
前兩章我為大家詳細介紹了如何搭建Maven環(huán)境、Spring MVC的流程結構、Spring MVC與Struts2的區(qū)別以及示例中的一些配置文件的分析。在這一章,我就對示例的層次結構進行說明,以及MyBatis的一些簡單介紹。 本文不會對MyBatis作詳細說明,大象還是假定閱讀本文的朋友對MyBatis(ibatis)有最基本的了解,只有這樣才能較好的理解本文的內(nèi)容。關于MyBatis請查看它的官方文檔及其它參考資料,本文不作詳細討論。
一、工程結構圖
上面這是典型的Maven項目結構形式,使用本地倉庫管理jar包的依賴,使用插件打包編譯發(fā)布非常方便,讓我們從傳統(tǒng)的開發(fā)方式中解放出來,大家都快來使用Maven構建項目吧!
二、映射文件
使用MyBatis進行持久化操作,需要設置一個映射文件,一般來說,每張表對應一個實體對象和一個mapper映射文件。而MyBatis里面沒有像Hibernate那樣復雜的關聯(lián)關系,所以,它的每個實體類其實就是一個很普通的POJO類。而映射文件中,都是SQL語句,下面就是示例中RoleMapper.xml的代碼片段。
那么,MyBatis是如何將數(shù)據(jù)庫字段與POJO對象進行映射的呢?這是在它的內(nèi)部,會將到得的結果或結構集,與我們定義的POJO對象屬性進行映射,規(guī)則是,屬性首字母小寫,使用駝峰式命名方式,而字段則是單詞與單詞間,用下劃線連接。比如:數(shù)據(jù)庫有個USER_NAME字段,那么與它對應的屬性就應該是userName。如果字段命名沒有使用下劃線,那么屬性可以直接定義成該單詞。比如,NAME字段,它的屬性就是name。
三、基于namespace接口與公用dao的區(qū)別
從MyBatis3.0開始,對mapper中的namespace屬性新增了一個特性:可以指定具體的接口來作為持久化操作類,在接口中定義與映射文件中id屬性值相同的方法,MyBatis會自動去綁定和執(zhí)行對應的SQL語句。這種接口實現(xiàn)方式,需要為每個Mapper創(chuàng)建一個接口,如果系統(tǒng)做大了,維護這些類會比較麻煩,大象個人傾向于基礎服務式的Dao實現(xiàn)類,如例子中的MyBatisDao。
四、MyBatisDao
持久化操作基類,SqlSessionDaoSupport是mybatis-spring插件中封裝的,用于獲得SQL Session連接,執(zhí)行數(shù)據(jù)庫操作,我定義了幾個常用的方法。
關于mybatis-spring插件我簡單介紹一下, Spring 3.x的發(fā)布并沒有對MyBatis這一優(yōu)秀的SQL框架提供支持,雖然在它的問題列表中已經(jīng)有這樣的請求,但直到目前3.0.5版的發(fā)布,都還沒將這個問題處理掉。不過這難不倒開源世界里廣大的愛好者與貢獻者,mybatis-spring就是在這樣的情況下誕生了。它是由MyBatis社區(qū)愛好者完成的一個開源項目,用來進行Spring 3.0與MyBatis 3.0的配置整合。該插件需要運行在JDK 5.0或更高版本。
五、Service
在
ssm3這個示例中,大家有沒有發(fā)現(xiàn),已經(jīng)沒有為每個entity定義一個dao,而是統(tǒng)一的調(diào)用MyBatisDao作為存儲服務接口。另外與使用Hibernate的主要區(qū)別,就是不能直接傳一個對象參數(shù),還必須寫上key值,它是namespace加上ID值。
六、entity
MyBatis的實體類就是一個簡單的POJO對象,只是用來與表字段進行關聯(lián)映射,請注意,我這里所說的映射不是像Hibernate那種綁定關系,只一種存放數(shù)據(jù)的對象而已。
七、測試 上面的步驟完成后,接下來就需要測試下我們的業(yè)務接口是否正常,編寫一個測試類,為了達到目的,簡便起見,大象是對RoleService進行測試,UserService同理類似。
在寫測試用例前,需要在POM文件中加入一個Srping測試依賴,這是大象在前面兩章疏忽漏掉了,請大家諒解。
然后編寫測試類,運行測試,通過!