本文的內容來自各種渠道,有朋友非正式的討論與郵件往來,也有網路上的各種資料,還有開發人員們口耳相傳的實踐經驗。為了方便讀者,我不揣冒昧將它們整理成對話的形式,並借了兩個虛構人物(WebWork的愛好者Weber和Struts的老使用者Steven)之口來比較這兩種流行的web架構,希望對讀者的選擇有所協助。
Steven:嘿,Weber,你最近忙什麼呢?
Weber:哦,我剛做了一個項目,用WebWork做的,感覺挺好。
Steven:WebWork嗎?我知道它,它有什麼好的?
Weber:好處可多了,比Struts強太多了。你用Struts那麼久,難道就不覺得有什麼不舒服的嗎?
Steven:恩……確實有一些。比如說,Struts的ActionForm其實不太好用,有點不倫不類的,平白的在action和view之間引入了麻煩。Struts最近的設計也逐漸在淡化ActionForm的作用了。
Weber:是呀。而且Struts的不爽的地方還有介面比較難看。action必須要實現繼承,到現在也沒有改為介面繼承。而且execute方法的介面也全是HttpServlet...,不能脫離servlet container,要測試還得提供mock的request,真是麻煩。
Steven:Struts由於要重用action的執行個體,因此不得不把所有狀態從action裡剔除,從而需要每次都傳入request/response,這是一個典型的無狀態設計,為pool和負載作了準備,理論上講效能的延展性要更好一些。Struts由於每次都要處理request/response,所以必須提供一些工具方法,於是Action不再是介面,而改成一個class,這個設計在ood裡也是常用的手法。如果沒有這些介面,又怎麼在servlet和action之間傳遞資料呢?
Weber:這就是WebWork的設計精彩之處了。action都是普通的JavaBean,它們只實現自己的業務功能,其他基礎設施級的功能——例如怎麼與servlet交換資料——都是用攔截器來實現的。正是因為有這個攔截器機制,所以WebWork才這麼好用呢。
Steven:不過我看WebWork提供的功能還是比較少,比如它自己就沒有資料校正的能力,必須要用別的工具來協助校正。
Weber:沒錯,但這種功能都可以用攔截器機制來做,你可以把這些攔截器抽象出來複用。所以WebWork本身不需要包含那麼齊全的功能,它只提供了一個靈活的核心,很多功能都可以做成外掛程式插進去。而Struts就比較麻煩了,新加一個功能就會傷筋動骨,所以Struts老是有很多新特性要發布呢。
Steven:是的。最近Struts又放出訊息,未來的版本將增加對JSR-168 portlet的支援。
Weber:這個問題在WebWork雷根本就不成問題。只要做一個portlet作為引擎,再修改幾個配置,所有的WebWork action都可以原封不動地移植到portlet環境,因為它們原本就是最普通的JavaBean,根本就不知道外面的環境究竟是servlet環境還是portlet環境。由於action不依賴具體的運行環境,所以單元測試也很方便,直接把action new出來,把參數設定進去就可以測試了。
Steven:說起測試嘛,拋開先富起來的地區不說,起碼中國還有1/3的軟體企業處在對TDD懵懂的階段吧?還有1/3的企業在追捧CMM和一些瀑布模型的開發方法吧?那麼對於這些企業,Struts和WebWork在易測上的差異他們是感受不到的。當前的狀態下,易測性並不是軟體企業技術選型的一個重點目標,那麼Struts就有了其生存的土壤。當然這就扯得有點遠了。
Weber:你說得很有道理。Struts好在夠多的人支援、使用,讓人覺得夠穩定、保險、有保障。要是做個項目,很多老闆一定說,我要的不是新技術,要的是穩定。所以我現在也還常常在用Struts開發項目。
Steven:看來我也應該多瞭解一下WebWork。如果以後採用TDD的開發方法,可測性的確是很重要的因素,那時也許我就會選擇用WebWork了。
Weber:還有一種折中的辦法,就是改造Struts,給它加上攔截器機制,然後再用攔截器來實現Dependency Injection,這樣可以把Struts變得跟WebWork一樣易用,而且又不會損失它原來的功能,實現起來也不算複雜。
Steven:確實不錯。這麼一來,我的工具箱裡又多了一種可選的方案了。
附錄:關於Struts與WebWork之間的技術比較,請看下列兩個地址:http://udoo.51.net/mt/archives/000044.html
http://wiki.opensymphony.com/display/WW/Comparison+to+Struts