敘述Servlet API的討論
JSR-315發布了Servlet 3.0規范的公開預覽版,同時在GlassFish代碼分支上提供了參考實現。這次發布引發了人們對于專家組(ExpertGroup)為下一代Servlet API和整個JavaEE6平臺做出的各種選擇的爭論。
Servlet API一直處于風口浪尖,從初期草稿開始,JSR315專家組致力于在類似便捷開發、插件性等領域完善和提高該規范,其***之一RajivMordani,這樣說道:
便捷開發(EaseofDevelopment):在早期草案中,我們添加了一些注解,允許你像POJO一樣寫Servlet 。但是在專家組的若干次討論和社區反饋之后,我們決定刪除像@GET,@POST這樣的方法層注解,保留doGet、doPos方法和擴展HttpServlet 類。但是,那些重命名以更有效使用的最頂層注解仍然存在。@WebServlet 用于聲明一個Servlet ,@Servlet Filter聲明過濾器,@WebServlet Context Listener定義Servlet Context Listener。除了這些注解,像@Resource這種自Servlet 2.5就一直支持的注解則保持不變。
可插入性:構建于Servlet 之上的Web框架在開發人員中很受歡迎,其中很多人提出了各種各樣的問題。為了更好地支持框架便于開發人員編寫web應用,我們在Servlet 3.0規范中添加一些方式以幫助開發人員根據自身情況使用和管理框架。
異步處理:這是我們在Servlet 3.0規范中變化***的部分。在早期草案中,我們暫停、重新開始、確定了我們定義的語義。但是,在這之后,專家組對于如何解決異步處理的各種用例進行了大量的討論,規范中做出的修改現在也可以解決各種問題。
RoyVanRijn表達了他對于早期草案中出現的一些特性的擔憂:
我更傾向于完全不使用針對GET/POST方法的注解,但是我發現JavaEE6規范提倡使用類似的注解,JSR-315的編寫者“別無選擇”(糟糕的借口)。我在本文中表達的觀點已經發給了JSR組織,但至今沒有回應。
我也找不到一名成員給出原因、解釋、澄清等等。最近JavaEE6規范發布公開預覽版,其中包含了對Servlet 3.0規范的引用,所以這會成為JavaEE6的一部分。但是我懇請他們花時間重新考慮關于注解的決定。
隨著規范公開預覽版的發布,來自Webtide的GregWilkins認為該規范非常糟糕,是不和諧的專家組和有缺陷的流程的產物。他的主要觀點包括:
它代表了API設計上的一次思想實驗,不關注實現的復雜性、試用可行性和社區反饋。
要求測試實現的請求被拒絕了。
沒有公開的或者合理的機制來收集來自社區的需求和寶貴的社區咨詢。
一些模糊的需求(比如包裝的異步請求)在較晚時候包含進來,沒有用例和用戶需求。
寫的非常糟糕,就像大多數JCP文檔一樣。
一些新的特性引起了安全隱患,并可能導致部署緩慢。
異步Servlet 的建議被改變了,與早期草案不同。最初的方法是JettyContinuations的結果,從2008年3月即可在Jetty-7pre-release中試用,已經在很多框架和應用中測試過,包括ometd、DWR、JSF和BlazeDS。
Greg總結說:
我相信在現在的預覽版中有明顯的錯誤,這些缺陷已經多的讓人很容易就可以發現。當我從專家組收到關于這些問題的支持信息時,我無法確信規范***的合法身份,我可能因為過于嚴厲而無法得到幫助了。
Rajiv對Greg的答復中指出:
在GlassFish中有相關實現。
他從沒看到過Greg的請求。
如果不喜歡新功能,可以禁止使用。
沒有明顯的證據表明部署會變慢。
異步Servlet 增加的方式更被社區所喜歡,他引用了專家組的郵件。
Rajiv也提到了來自RedHat的BillBurke寫的一篇博文,其中他批評了Jetty6中的異步Servlet 實現。
隨后,GregWilkins宣布他致力于Servlet 3.0異步Servlet 的一個實現,他在博客上列舉了一些修正/擴展和與專家組的持續討論。其中包括:
新的異步分發器類型(ASYNCDispatcherType),用于分發異步請求。
當請求分發時,isAsyncStarted()方法為false。
如果getReader()或者getOutputStream()已經被調用,則調用startAsync()或者startAsync(request.response)時會拋出IllegalStateException異常。這可以把異步處理器限制到簡單的情況下。
如果通過startAsync(request,response)啟動異步模式,在AsyncContext 上使用任何forward(...)方法都會有IllegalStateException異常。這避免了分發包裝器的復雜,但允許異步處理器使用包裝器。
forward(path)和forward(Context ,path)方法還沒有實現。
代碼可以從Jetty分支和Servlet -api分支中得到。
Grep談到了異步Servlet 的事情:
雖然還需要更多測試,但是這個代碼已經實現了基本的異步行為,不需要很復雜的重新分發請求或者前遞方法。我相信這代表了3.0的合理折中方案。在我們從3.0的簡單子集里獲得經驗之后,如果需要更多的特性,可以添加到3.1中。
【編輯推薦】