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