隨著Java EE 8在2017年9月22日釋出,Servlet的版本也來到了4.0!什麼?Servlet?在前端工程當道的這些年來,這個依附在Java EE上的後端Web技術,還值得一提嗎?而且,還不是提JSP,而是Servlet?

其實,在Java EE的Web層這塊,也許Servlet才仍然值得一提!

JSP過時了?

這些年來前端工程興起,大量的新聞與文件集中於前端技術,後端開發則像是過氣的明星,在缺乏鎂光燈的舞臺默默地持續演出,加上Java重大版本延期已成固定戲碼,Oracle與Google的官司失利,傳出對Java失去了興趣,Java相關開發者、傳教士的離去,Java EE發展遲緩,這次不僅是Java已死,而是Java EE已死的論調也出現了。確實地,這些年來,我也花較多時間在其他開放原始碼專案上,而少於關注Java EE。

然而,Java EE 8釋出之後,我有一本被出版社編輯關切多次的Servlet著作,必須得好好確認一下,是否有改版的價值。書中現有的版本,是基於Java EE 6/Servlet 3.0/JSP 2.2,而Java EE 7的規格是Servlet 3.1/JSP 2.3,Java EE 8則是Servlet 4.0/JavaServer Pages 2.3?嗯?從版號上來看,JSP你還好嗎?

差不多自Java EE 5之後,發生了JavaScript的再興、行動裝置的普及,Web這部分一路走來,歷經了很大的變化,先不論前端工程,後端的Java Web框架本就不少,加上還有其他技術,像是Rails、Node.js的攻城掠地,JSP可以發揮的空間確實是變少了。對此,有一個指標性的代表,是Java官方網站上的Java EE Tutorial,從Java EE 6開始就沒有JSP的內容了,JSF的內容成了實作Web層呈現時的主角。

如果真的想在Java EE Tutorial中,查看JSP的文件,Java EE 6之後的版本都會請你去看Java EE 5 Tutorial。國外鄉民的說法之一是,Oracle為了推動JSF而這麼做,說法之二是JSP已經過時,而拿來說嘴的根據,是《Java EE 6 Tutorial》第5章〈Introduction to Facelets(https://goo.gl/B3XFVw)〉的一段話:「對JSF來說,JSP被認為是不建議使用(deprecated)的呈現技術。」

雖然只是作為認識Java EE的起點文件(內容編排上還有點無聊),然而終究是官方文件,無論是拿掉了JSP的說明,或是在文件中明指不建議使用JSP(作為JSF的呈現技術),總是有一定的指標意義,所以,JSP真的過時了嗎?

Java EE規格怎麼說?

如果JSP真的過時了,那麼,Java EE規格應該會有什麼變化!實際上,一直到Java EE 8,JSP還是明列在Java EE規格之中,不過JSP 2.2、2.3之間沒什麼新功能——基本上,是進行維護方面的清理,或因應EL、JSF規範方面的新增,而作出必要的修改。若要說有什麼不同,JSP 2.3是有了新的明定,JSP容器必須針對HTTP的GET、POST、HEAD方法,做出對應的呈現(其他方法則未定義)(https://goo.gl/aq96A9)。

至於跟JSP相關的規格,一直都是獨立發展,像是EL、JSF。雖說JSF想拋棄JSP(而改基於Facelets),不過,在Java EE 8中,JSF 2.3仍使用JSP API,MVC 1.0也支援JSP,而JSP的基礎Servlet在Java EE 8中,也從3.1版跳到4.0,突顯規格有了很大的不同。

實際上,瞭解Servlet的開發者就會知道,JSP本身在應用上不需要太多著墨。畢竟,技術面上,多半是Servlet的對照,Servlet才是Web應用程式的入口,雖然開發者很少直接撰寫Servlet,然而許多框架技術都是以Servlet為核心而撰寫,若瞭解與掌握Servlet,也就能掌握JSP或相關框架。就現在的眼光來看,當年直接把JSP當PHP在介紹,完全不提或只提一丁點Servlet的書或文件,感覺才是魔道了。

也因此,Java EE一直在Servlet的規格上演進。從3.0支援標註等各方式的設定簡化,到3.1支援HTTP/1.1與非阻斷IO,4.0也在HTTP2上有更多的支援等,而且,就算是Java EE 8 Tutorial,也還是捨棄不了Servlet的相關說明。

就今日眼光來看,JSP確實在Web呈現有所不足,然而基於JSP的舊東西也不少(包括許多Web框架),國外有許多鄉民也表示,還捨棄不了JSP,只是有些鄉民會建議,如果可以的話(像是新專案,而使用的框架支援JSP以外的呈現技術),想考慮使用其他呈現技術來取代JSP。

基於Java 8的Servlet 4.0

既然Servlet依舊重要,因為Java EE 8正式釋出了,那麼,就來關切一下Servlet 4.0到底有什麼變化吧!

首先,Java EE 8是基於Java SE 8,這就代表了在撰寫Servlet時,可以使用到Lambda表示式、Stream之類的函數式風格程式庫,而在非同步處理時,也可以考慮改用CompletableFuture之類的API。

在Servlet 4.0,一些介面實作時,使用了Java SE 8新增的預設方法語法,像是ServletContextListener、HttpSessionListener、Filter等介面,在實作時,也就只需要針對感興趣的方法重新定義,而不需要實作全部的方法,或者自行寫個Adapter了。

談到Servlet 4.0,許多文件上都會談到對HTTP/2的支援,而在API層面上,開發人員可以使用HttpServletRequest的newPushBuilder方法,來建立PushBuilder以支援HTTP/2的Server Push(Tomcat等容器必須基於HTTPS連線才能支援);Servlet 4.0也支援HTTP Trailer標頭,在API上,可使用HttpServletRequest、HttpServletResponse的getTrailerFields、setTrailerFields等方法。

其他,還有一些瑣碎改進,也值得一提。例如:HttpServletRequest新增getHttpServletMapping方法,可以取得HttpServletMapping實作物件,以便在執行時期偵測執行中的Servlet,是透過哪個URL模式對應而來。類別上,也新增加了HttpFilter,父類別為GenericFilter,並且實作了Filter介面。顯然地,實作概念上,類似HttpServlet繼承GenericServlet實作Servlet介面,開發者現在可以繼承HttpFilter,重新定義HttpServletRequest、HttpServletResponse版本的doFilter(而不是ServletRequest、ServletResponse版本)來實作過濾器。

在部署設定上,現在可以在web.xml中,設定<default-context-path>(容器實作廠商的context path設定可以覆蓋此預設);可以透過<request-character-encoding>、<response-character-encoding>,設定預設的請求回應編碼,以往這類編碼設定,必須自行透過過濾器的實現來達成。

如果在應用程式初始階段,須用ServletContext,來進行<request-character-encoding>之類的設定,目前,在ServletContext上,也新增了setRequestCharacterEncoding等對應的方法。

微服務基礎的Servlet?

可以確認的是,現今JSP在呈現技術的角色上,已經沒那麼重要了,然而,若仍然得基於Java EE,在Web層這塊難免都會碰到Servlet相關議題,要擔心的也許是Java EE的發展。

許多社群成員都曾砲轟Oracle無心Java EE,然而,問題也不是馬上捨棄Java EE就能簡單解決。對社群來說,可能是個好消息的部分是,Oracle將Java EE技術,重新授權給Eclipse基金會,並預計在Java EE 9改良Java EE,以便於實現微服務(Microservices)。

在這樣的藍圖,Servlet也許更形重要,在〈Servlet 4.0 JavaOne 2017(https://goo.gl/dfaU8G)〉的一開始,就談到了Servlet作為微服務基礎的初步概念。當然,Java EE的主導權才剛釋出,一切尚在未定數,然而Java開發者應是樂見有所成果。

若是如此,在Java EE 8釋出後,看一眼Servlet 4.0、瞭解進展,仍有意義,就可能性來說,Servlet規格(以及相關的Java EE規格)仍持續演進下去!

專欄作者

熱門新聞

Advertisement