首先,看看在使用struts等框架做開發的時候,遇到的一些問題:
1.從URL到Action B和S之間是HTTP,我們在http中能夠表達的僅僅是一個URL和若干字符串格式的參數。于是在任何業務開發過程中,我們都少不了從前端的URL+參數到后端的業務方法之間的映射。這個事情是枯燥無味的,是沒有技術含量的,是可以被認為是體力活的--但卻是不得不做的。
2.請求一個展現數據的頁面,一定是先到Action,準備數據,然后forward到頁面,這與早期的jsp+javabean開發或者asp開發中是完全相反的,后者實際上是你請求某頁面,那么你首先就是到達這個頁面,在這個頁面的處理過程中,再去做諸如準備數據這樣的事情。我認為后者這種方式才是更加自然的方式。
3.后端不知前端有什么 一次請求從前臺提交到后臺的時候,應用服務器把HTTP請求包裝成request對象,并把所有的請求參數放在其中。于是,當后端接收到一個參數的時候,我們不知道這個參數在前端對應著什么樣的html元素。這個問題在處理下拉框輸入的時候尤為突出。我們寫頁面的時候通過定義select下面的option元素告訴應用,說只能選某幾個選項其中之一,然后為了確保數據正確,在后端我們還是要校驗用戶的輸入是否是那幾個選項中的一個。這相當于我們兩次告訴系統輸入的允許范圍。為什么不能只做一次呢。因為在以往的開發過程中,后端不知道前端有什么。
4.無狀態的Action層 在以往的開發中,另外一個很重要的問題是關于狀態的。HTTP是無狀態的協議,于是基于HTTP的jsp、struts也都是無狀態的。什么是無狀態呢,典型的表現就是,你第一次請求查詢出來的一條數據,在下一次請求的時候,一定已經找不到了(我們不可能把大多數如此普通的數據簡單的放到session/application作用域中去)。這代表著使用Hibernate的場景下,為了正確的更新一個對象,你需要在提交表單的時候再次查詢數據庫獲得這個對象,然后把用戶修改了的屬性Set到這個對象上,然后再保存之。同時,為了實現樂觀鎖定,你需要把version信息也放在表單上發送給客戶端--如果客戶端傳回給你一個虛假的非常高的版本號,那么你的樂觀鎖形同虛設--兩個人同時打開某一條記錄,后提交的那個人完全可以在誰都不知情的情況下覆蓋前一個人的提交結果。
JSF/seam為我們解決了這些問題。基于JSF,我使用Spring替代了Seam,同樣能夠解決這些問題。
對于JSF每次點擊commandLink就要提交一下當年的form,我覺得這是對網絡資源的浪費。雖然JSF組件化開發,提高了軟件開發效率,但我不認為這種設計是優雅的。
無狀態是HTTP的固有屬相,這種固有屬性,并不會對交互帶來更多的副作用,而恰恰有其很大的優點:那就是可以將軟件設計成分布式的系統,通過每次客戶端去通知服務器端的狀態(狀態轉移),來完成一次交互,從而將客戶端與服務器端完全解耦,因此基于HTTP的B/S結構的軟件框架都應該更多的利用這種無狀態的有點。Struts1.2那種action的方式,并不是充分利用了HTTP的無狀態特性。據說Strtus2.0有REST的插件,不知作者有沒有去研究,或者你可以關注下Jersey這個框架,相信你會有更多的體會。。。
JSF更多的優點是:對客戶端組件化開發提供了簡單靈活的構建方式,提高了UI開發的生產力,這種利用HTTP協議,通過改造Servelt生命周期來實現基于事件的框架,也簡化了請求映射關系,使得開發更多關注業務,組件能夠大量重用。另外值得一提的是,JSF開發甚至不需要UI設計師的參與,從前臺到后臺同一工程師就能搞定,因為它不需要更多的前臺技術。
總之,Jersey等Restful的框架是優雅的,更高效的,更靈活的;JSF是高效的,可重用的,各有各的優勢。