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