Servlet 4.0 入門

Java™ Servlet API 是主流服務器端 Java 的基本構建塊,也是 Java EE 技術的一部分,例如,用於 Web 服務的 JAX - RS、JSF (JavaServer Faces) 和 JSP (JavaServer Pages)。Java servlet 也獨立存在,提供一系列支持動態 Web 內容的功能。其中包括過濾器、Web 安全性以及用於處理 HTTP 請求和響應的功能。css

Servlet 4.0 是 API 的最新版本,也是 Java EE 8 規範的核心更新。正如您將在本教程中瞭解到的,Servlet 4.0 已爲 HTTP/2 準備就緒,徹底包含服務器推送,同時還將其擴展到基於 servlet 的技術,如 JSF 2.3。本教程還介紹了新型 HttpServletMapping 接口, 它支持運行時發現 servlet 的映射 URL。html

Servlet 簡介

Java servlet 是一項基於 HTTP 協議運行的服務器端技術。Servlet 等待客戶端向服務器發送請求消息,而後向客戶端返回響應消息。請求和響應消息由兩部分組成:github

  • 標頭包含消息相關信息。
  • 主體包含消息的有效載荷,即其內容。

在傳統交換中,客戶端經過從瀏覽器或 curl 等另外一個 HTTP 客戶端請求特定的 URL 來調用 servlet。web

在清單 1 中,請求 servlet 路徑時,會激活該 servlet 。請求會被委派給相應的方法,這由 HTTP 方法來肯定。在這種狀況下,因爲請求是 GET 方法請求,所以經過 Java servlet 的 doGet() 方法來處理該請求。瀏覽器

如下交換的 servlet 路徑是:http://hostname/applicationroot/showlogoservlet.緩存

清單 1. servlet 簡單實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@WebServlet("/showlogoservlet")
public class SimpleServlet extends HttpServlet {
 
    @Override
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
                         throws ServletException, IOException {
 
        getServletContext()
          .getRequestDispatcher("/showlogo.jsp")
          .forward(request, response);
 
    }
}

Servlet 4.0 的主要新功能

Servlet 4.0 的主要新功能爲服務器推送和全新 API,該 API 可在運行時發現 servlet 的 URL 映射。安全

服務器推送是最直觀的 HTTP/2 強化功能,經過 PushBuilder 接口在 servlet 中公開。服務器推送功能還在 JavaServer Faces API 中實現,並在 RenderResponsePhase 生命週期內調用,以便 JSF 頁面能夠利用其加強性能。服務器

全新 servlet 映射發現接口 HttpServletMapping 使框架可以獲取有關激活給定 servlet 請求的 URL 信息。這可能對框架尤其有用,這些框架須要這一信息來運行內部工做。

在接下來的部分,我將概述服務器推送及其如何在 Java servlet 中運行,包括 JSF 2.3 中的服務器推送。我還將展現一個交換示例,重點介紹全新 servlet 映射發現功能。

Servlet 4.0 中的服務器推送

服務器推送使服務器能預測客戶端請求的資源需求。而後,在完成請求處理以前,它能夠將這些資源發送到客戶端。

要了解服務器推送的好處,能夠考慮一個包含圖像和其餘依賴項(好比 CSS 和 JavaScript 文件)的網頁。客戶端發出一個針對該網頁的請求。服務器而後分析所請求的頁面,肯定呈現它所需的資源,並主動將這些資源發送到客戶端的緩存。

在執行全部這些操做的同時,服務器仍在處理原始網頁請求。客戶端收到響應時,它須要的資源已經位於緩存中。

PushBuilder

Servlet 4.0 經過 PushBuilder 接口公開服務器推送。爲了可以進行訪問,您須要經過調用newPushBuilder() 方法,從 HttpServletRequest 獲取 PushBuilder 實例。清單 2 展現瞭如何獲取 PushBuilder 實例。

清單 2. 如何獲取全新 PushBuilder
1
2
3
4
5
6
7
8
@Override
protected void doGet(HttpServletRequest request,
                      HttpServletResponse response)
                      throws ServletException, IOException {
 
    PushBuilder pushBuilder = request.newPushBuilder();
 
}

每次調用 newPushBuilder() 方法時,都將返回 PushBuilder 的新實例。若是服務器推送不可用,newPushBuilder() 將返回 null。在某些狀況下,客戶端可能會爲請求事務拒絕服務器推送。若是客戶端沒有使用安全鏈接,服務器推送也不會起做用。所以,務必要在對 PushBuilder 實例調用方法以前,針對 null 返回值進行測試。

顧名思義,PushBuilder 實現 Builder 模式。在這一實現過程當中,經過連接賦值方法構建推送請求。這些賦值方法經過設置 HTTP 標頭、方法類型(GET 是惟一的可接受值)、查詢字符串、會話 ID 和資源路徑(即,將要推出資源的路徑),來配置 PushBuilder 實例。

大多數來自原始 HttpServletRequest 實例的請求標頭,只添加到 PushBuilder 實例中。因爲正確運行服務器推送並不須要某些標頭,所以不包括如下標頭:

  • 條件標頭
  • Range 標頭
  • Expect 標頭
  • Authorization 標頭
  • Referrer 標頭

如今,讓咱們看看如何構造和引起服務器推送操做。

1.設置推送資源

這一路徑是在向客戶端推送資源以前必須設置的惟一配置。設置路徑須要調用 path() 方法。該方法只能被調用一次,由於它會改變 PushBuilder 對象的路徑值。該路徑可能會以正斜槓(「/」)開頭,指示資源路徑是絕對路徑;不然,該資源會被認爲是相對於關聯請求的上下文路徑。該路徑能夠包含一個查詢字符串,該查詢字符串將與 queryString() 方法設置的任何字符串合併。

2.推送資源

接下來,您將調用 push() 方法, 將資源推送到客戶端。push() 方法用於發起與客戶端的推送「對話」。在後臺,會向客戶端發送一個 PUSH_PROMISE 幀,相似於發送資源的意圖通知。客戶端能夠經過發回 RST_STREAM 來拒絕資源。這種機制容許客戶端保留對接收到的資源的控制。所以,客戶端不會因不須要的資源或已經在緩存中的資源而過載。

如清單 3 所示,一旦得到了 PushBuilder 的實例,就能夠屢次重複使用。路徑和條件標頭都爲 null,可是全部其餘字段都原樣保留。這些能夠在另外一個服務器推送中重複使用。

清單 3. 重複使用 PushBuilder 實例
1
2
3
4
5
6
7
PushBuilder pushBuilder = request.newPushBuilder();
 
if (pushBuilder != null) {
    pushBuilder.path("images/hero-banner.jpg").push();
    pushBuilder.path("css/menu.css").push();
    pushBuilder.path("js/marquee.js").push();
}

在清單 3 中,hero-banner.jpg 的路徑是經過 path() 方法在 PushBuilder 實例上設置的,並經過調用 push() 推送到客戶端。push() 方法是非阻塞的,且當即返回,以便後續可推送更多資源(本例中爲menu.css 和 marquee.js)。

服務器推送實戰

將服務器推送與 JSF 結合使用

JavaServer Faces 已經將每一個頁面的資源需求標識爲頁面呈現生命週期的一部分,因此它很是適合用於服務器推送。就開發人員而言,比較好的一方面是,您沒必要爲了激活此功能而煞費苦心。您能夠免費升級到 JSF 2.3。

清單 4 展現了JSF 和服務器推送的集成狀況。

清單 4. 在 JSF 頁面中使用服務器推送
1
2
3
4
5
6
7
8
9
10
11
< h:head >
    < h:outputStylesheet library = "css" name = "logo.css" />
    < h:outputScript library = "js" name = "logo.js" />
    < title >JSF 2.3 ServerPush Example</ title >
</ h:head >
< h:body >
    < h:form >
        < h:graphicImage library = "images" name = "logo.jpg" />
    </ h:form >
</ h:body >
</ html >

清單 4 中的 JSF 頁面須要如下三種資源:

  • 名爲 logo.css 的 CSS 文件。
  • 名爲 logo.js 的 JavaScript 文件。
  • 名爲 logo.jpg 的圖像。

當 JSF 引擎正在處理和呈現頁面時,這些資源將被逐個推送到客戶端。這發生在 JSF 的呈現響應階段。而後,會爲每一個資源調用 ExternalContextImpl.encodeResourceURL() 方法,並向其傳遞資源的新 URL。從與 ExternalContext 相關聯的 HttpServletRequest 實例獲取新的 PushBuilder 對象。若是支持服務器推送,那麼會在向客戶端呈現頁面以前將資源推送到客戶端。

 

HttpServletMapping 接口

Servlet 4.0 的全新 servlet 映射發現 API 使服務器可以對 URL(可調用 servlet)執行運行時檢查。例如,對 file.ext, /path 和 /path/file.ext 的請求將經過 URL 模式 /path/* 和 *.ext 激活 servlet。

HttpServletMapping 接口支持運行時發現 servlet 的映射 URL。您能夠在 HttpServletRequest 實例上調用 getHttpServletMapping(),獲取接口的實例。您可使用如下方法獲取有關 servlet 映射 URL 的信息:

  • getMatchValue() 返回部分 URI 路徑,該路徑會致使請求匹配。
  • getPattern() 返回 URL 模式的 String 表示形式。
  • getServletName() 返回 servlet 名稱的 String 表示形式。
  • getMappingMatch() 返回匹配的類型,表示爲 MappingMatch 枚舉值,該枚舉值將爲如下值之一:CONTEXT_ROOTDEFAULTEXACTEXTENSION 或 PATH

清單 5 展現了四種 API 方法的實際應用。

清單 5. Servlet 4.0 中的運行時 servlet 映射發現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@WebServlet({"/path/*", "*.ext"})
public class ServletMapping extends HttpServlet {
 
     protected void doGet(HttpServletRequest request,
                          HttpServletResponse response)
                          throws IOException {
 
         HttpServletMapping mapping = request.getHttpServletMapping();
         String mapping = mapping.getMappingMatch().name();
         String value = mapping.getMatchValue();
         String pattern = mapping.getPattern();
         String servletName = mapping.getServletName();
    }
 
}

 

Servlet 4.0 的細微變化

除了服務器推送和全新 HttpServletMapping 接口,Servlet 4.0 還包括少許值得注意的新增功能和變動。

  1. Trailer 響應標頭支持發送方在分塊消息的末尾包含額外字段。這用於提供在發送消息主體時可能會動態生成的元數據,例如,消息完整性檢查、數字簽名或後期處理狀態。
  2. Servlet 4.0 添加了 GenericFilter 和 HttpFilter 抽象類,這些抽象類經過最低限度地實現生命週期方法 init() 和 destroy(),簡化了編寫過濾器。
  3. Servlet 4.0 還集成了全新的 HTTP Trailer,支持發送方在分塊消息的末尾包含額外的字段。
  4. ServletContext 接口採用了一些新方法:
    • addJspFile() 可將帶有給定 JSP 文件的 servlet 添加到 servlet 上下文中。
    • getSessionTimeout() 和 setSessionTimeout() 可提供對會話超時的訪問權限。
    • getRequestCharacterEncoding() 和 setRequestCharacterEncoding() 可爲當前的 servlet 上下文提供訪問權限,並改變默認的請求字符編碼。
  5. HttpServletRequest 接口上的 isRequestedSessionIdFromUrl() 方法已被棄用。
  6. 因爲升級到 Java SE 8,默認方法已被添加到偵聽器接口中。

結束語

Servlet 4.0 已經發布,主要用於整合全新 HTTP/2 協議及其衆多性能加強功能。PushBuilder 接口對推送到客戶端的資源提供細粒度控制,使交叉實現生動有趣。例如,Jetty 9 在 PushCacheFilter Web 過濾器中使用 PushBuilder API 實現了服務器推送功能。此過濾器在首次請求時緩存了資源。即便仍在服務器端處理請求,它也可以將後續請求推送到客戶端。

雖然 JSF 2.3 內置了服務器推送功能,但 JavaServer Pages 並無此功能。JSF 與服務器推送的集成十分有用,開發人員於是可減小對性能問題的關注,而更加着力於設計動態網頁。對於想要在 JSP 中實現類似功能的開發人員,就須要使用 Web 過濾器這樣的定製解決方案,例如 Jetty 9 中的 PushCacheFilter Web 過濾器。

 

原文出處

Alex Theedom,Servlet 4.0 入門,https://www.ibm.com/developerworks/cn/java/j-javaee8-servlet4/index.html?ca=drs-&utm_source=tuicool&utm_medium=referral

相關文章
相關標籤/搜索