1 // 執行過濾的核心方法 2 public void doFilter(ServletRequest request, 3 ServletResponse response, FilterChain chain) 4 throws IOException,ServletException 5 { 6 // ---------下面代碼用於對用戶請求執行預處理--------- 7 // 獲取ServletContext對象,用於記錄日誌 8 ServletContext context = this.config.getServletContext(); 9 long before = System.currentTimeMillis(); 10 System.out.println("開始過濾..."); 11 // 將請求轉換成HttpServletRequest請求 12 HttpServletRequest hrequest = (HttpServletRequest)request; 13 // 輸出提示信息 14 System.out.println("Filter已經截獲到用戶的請求的地址: " + 15 hrequest.getServletPath()); 16 // Filter只是鏈式處理,請求依然放行到目的地址 17 chain.doFilter(request, response); 18 // ---------下面代碼用於對服務器響應執行後處理--------- 19 long after = System.currentTimeMillis(); 20 // 輸出提示信息 21 System.out.println("過濾結束"); 22 // 輸出提示信息 23 System.out.println("請求被定位到" + hrequest.getRequestURI() + 24 " 所花的時間爲: " + (after - before)); 25 }
第8行,從Filter 子類的this中獲取ServletContext對象。php
第12行,從參數request強制轉換爲HttpServletRequest對象。java
第14行,打印截獲的用戶請求的地址web
第17行,filter鏈式處理用戶請求和應答編程
容器在部署時會處理XML片斷並組裝成最終的部署描述符。因爲容器負責組裝web.xml文件,所以若是須要按照特定的順序來調用框架的 Servlet、Listener或Filter時就可能產生問題。爲了不這個問題,Servlet 3.0 API支持絕對與相對順序的部署描述符。咱們能夠在web.xml文件中使用元素指定絕對順序,這樣 WEB-INF/lib下的每一個jar均可以經過META-INF/web-fragment.xml文件的元素得到一個名字。接下來,Web應用的WEB-INF/web.xml文件能夠經過元素按照順序列舉出這些片斷名,這個順序就是jar的調用順序,同時還有一個可選的元素用於指定是否以及什麼時候包含那些未命名的jar文件。因爲部署者能夠選擇只列出那些受信任的jar以進行部署,這樣就能夠避免意外狀況的發生。除此以外,經過順序還能夠排除那些不須要被掃描的jar,這樣就能夠加快應用的部署速度。最後,若是你不想在產品環境下看到自我註冊的狀況發生,那就能夠在web.xml文件中使用 元素,這會告訴Web容器只去尋找註解而非Web片斷。瀏覽器
因爲既支持片斷,又可使用註解做爲另外一種配置機制,Servlet 3.0能夠插入框架的共享拷貝,好比JAX-WS、JAX-RS以及JSF等,他們都構建在Web容器之上,使用了 ServletContainerInitializers。這些框架是經過jar services API被檢測到的,同時還能夠指定其處理的類型列表。對於WEB-INF/lib下的任何jar來講,只要其中包含的類被檢測到都會傳遞給 ServletContainerInitializer。這樣,咱們還能夠將一樣的API做爲ServletContextListeners。服務器
從Servlet API首次發佈以來,構建Web應用的方法發生了翻天覆地的變化,尤爲是使用愈來愈多的異步Web技術。這些技術(通常統稱爲Ajax或是Web 2.0)對於Web客戶端(好比瀏覽器)與服務器端之間的傳輸機制產生了重要的影響,由於客戶端會在一個頁面中向服務器端發出更多的請求而不是每次請求都刷新一次頁面。cookie
長時間的服務器端處理會惡化這一狀況,好比等待JDBC鏈接池中的鏈接,或是等待JMS隊列中的消息等。在Servlet中等待實在是過低效了,由於這種阻塞會消耗線程以及其餘有限的系統資源。鑑於此,Servlet 3.0引入了異步處理請求的功能,這樣線程就能夠返回到容器中並執行其餘任務。在請求上的異步處理開始時,其餘線程或是回調既能夠生成響應,也能夠分發請求以便經過AsyncContext.dispatch方法在容器上下文中執行請求。session
因爲異步Servlet的行爲與同步的差異很是大,所以Servlet 3.0要求開發者指定asyncSupported=true以表示Servlet支持異步請求。不只是Servlet,Filter也能夠異步執行。 Servlet 3.0經過新的ServletRequest方法來支持異步處理,好比startAsync()會返回一個AsyncContext對象,該對象用於持有傳遞給方法的request與response對象。這裏,處理原始請求的線程還能夠執行其餘操做。此外,API還引入了一個新的Listener 類:AsyncListener,它會告訴咱們異步操做什麼時候結束或者是否超時了。AsyncContext類擁有一個complete()方法,憑藉該方法咱們能夠在異步操做結束後提交響應。AsyncListener類擁有一個dispatch()方法,它會將異步請求轉發給容器,這樣其餘框架(好比 JSP)就能夠生成響應了。框架
除了引入大量的新技術和新方法外,Servlet 3.0規範還對其餘地方進行了大量的加強:HttpServletRequest終於得到對multipart/form-data MIME類型的內置支持了、Cookie類開始支持「HttpOnly」 cookie以免某些跨站點的腳本攻擊、ServletContext API也獲得了更新,咱們能夠經過編程的方式將Servlet和Filter加到上下文中了。異步
例子:
1 @WebServlet(name="CalculatorServlet", asyncSupported=true, urlPatterns={"/calc", "/getVal"}) 2 public class CalculatorServlet extends HttpServlet{ 3 public void doGet(HttpServletRequest req, HttpServletResponse res) { 4 ... 5 AsyncContext aCtx = req.startAsync(req, res); 6 } 7 ... 8 }