Servlet&JSP的那些事兒(十四)

來源:互聯網
上載者:User

本篇我們討論過濾器(Filter)。過濾器就是在來源資料和目的資料之間起過濾作用的中間組件。過濾器可以截取用戶端和資源之間的請求與響應訊息,並對這些訊息進行過濾。

當web容器接收到一個對資源的請求時,它先判斷是否有過濾器與這個資源相連,如果由,容器會把請求交給過濾器處理。在過濾器中,你可以改變請求的內容,或者重新佈建要求的前序資訊等。當目標資源對請求作出響應時,容器同樣會將響應先轉寄給過濾器,在過濾器中,你可以對響應的內容進行轉換,然後再將響應發送到用戶端。過濾器對用戶端和目標資源來說是透明的。

可以在web應用程式中部署多個過濾器,組成過濾器鏈。過濾器鏈中的每個過濾器負責特定的操作和任務。過濾器的主要應用如下:

對使用者請求進行統一認證
對使用者的請求進行記錄和審核
對使用者發送的資料進行過濾和轉換
轉換映像格式
對響應內容進行壓縮,以減少傳輸量
對請求和響應進行加密處理
觸發資源訪問事件

Filter API

和過濾器開發相關的介面與類都包含在javax.servlet和javax.servlet.http包中,主要有以下介面和類。

javax.servlet.Filter//介面javax.servlet.FilterConfig//介面javax.servlet.FilterChain//介面javax.servlet.ServletRequestWrapper//類javax.servlet.ServletResponseWrapper//類javax.servlet.http.HttpServletRequestWrapper//類javax.servlet.http.HttpServletResponseWrapper//類

我們先介紹三個主要的介面。

Filter介面

開發過濾器要實現Filter介面。Filter介面定義了三個方法。

1)init(),web容器調用該方法來初始化過濾器。容器在調用該方法時,向過濾器傳遞FilterConfig對象,FilterConfig用法和ServletConfig相似。利用FilterConfig可以得到ServletContext對象,以及在部署描述檔案中配置的過濾器的初始化參數。

2)doFilter,該方法類似於servlet的Service()方法。當用戶端請求目標資源時,容器就會調用與這個目標資源管理的過濾器的doFilter()方法。在這個方法中,可以對請求和響應進行處理,處理完後,也可以調用chain.doFilter(request,response)將請求傳遞給下一個過濾器,也可以直接傳回用戶端。

3)destroy(),web容器調用該方法指示過濾器的生命週期結束。在這個方法中,可以釋放過濾器使用的資源。

與開發servlet不同的是,Filter介面並沒有相應的類可供繼承,要開發過濾器,只能實現Filter介面。

FilterConfig介面

該介面由容器實現,類似於servlet的ServletConfig介面,用於在過濾器初始化時向其傳遞資訊,在該介面中,定義了一下4個方法。

1)getFilterName(),得到在部署描述檔案中指定的過濾器的名字

2)getInitParameter(String name),得到在部署描述檔案中指定的名字為name的初始化參數的值

3)getInitParameterNames(),返回過濾器的所有初始化參數的名字的枚舉集合。如果沒有初始化參數,則返回空值。

4)getServletContext(),返回servlet內容物件的引用。

FilterChain介面

該介面由容器實現,容器將其執行個體作為參數傳入過濾器對象的doFilter()方法中。過濾器對象使用FilterChain對象調用過濾器鏈中的下一個過濾器,如果該過濾器是過濾器鏈的最後一個過濾器,那麼將調用目標資源。它只有一個方法:

doFilter(request,response),調用該方法將使過濾鏈中的下一個過濾器被調用。如果調用該方法的過濾器是鏈中最後一個,那麼目標資源將被調用。

過濾器的部署

在實現一個過濾器後,需要在部署描述檔案中對過濾器進行配置。配置通過<filter>和<filter-mapping>來完成。一個配置描述檔案的樣本如下:

<?xml version='1.0' encoding='utf-8'?><web-app xmlns="http://java.sun.com/xml/ns/javaee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  version="3.0"  metadata-complete="true"><filter><filter-name>TestFilter</filter-name><filter-class>com.shan.filter.TestFilter</filter-class><init-param><param-name>word</param-name><param-value>/WEB-INF/word.txt</param-value></init-param></filter><filter-mapping><filter-name>TestFilter</filter-name><url-pattern>/test.jsp</url-pattern><servlet-name>servlet1</servlet-name><servlet-name>*</servlet-name><dispatcher>REQUEST</dispatcher></filter-mapping></web-app>

其中,<url-pattern>元素指定過濾器關聯的URL樣式,<servlet-name>指定過濾器對應的servlet。如果<filter-mapping>該值為*,表示對於任意的servlet。<filter-mapping>元素還可以包含最多4個<dispatcher>元素。該元素指定過濾器對應的請求方式,可以是REQUEST,INCLUDE,FORWARD,ERROR中的一個。預設是REQUEST。

現在我們來看一個過濾器的Demo程式。項目建立步驟和之前的完全相同,在此不再贅述。

編寫過濾器類

package com.shan.filter;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class TestFilter implements Filter {public void init(FilterConfig config) throws ServletException {}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {response.setContentType("text/html;charset=gb2312");PrintWriter out = response.getWriter();out.println("Before doFilter()");chain.doFilter(request,response);out.println("After doFilter()");out.close();}public void destroy() {}}

編寫測試頁面

<%@ page contentType="text/html;charset=gb2312" %>This is a test page..

編譯和部署過濾器

<?xml version='1.0' encoding='utf-8'?><web-app xmlns="http://java.sun.com/xml/ns/javaee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  version="3.0"  metadata-complete="true"><filter><filter-name>TestFilter</filter-name><filter-class>com.shan.filter.TestFilter</filter-class></filter><filter-mapping><filter-name>TestFilter</filter-name><url-pattern>/test.jsp</url-pattern></filter-mapping></web-app>

在dos環境下切換到工程所在目錄,執行如下語句,對TestFilter類進行編譯

javac -classpath D:\apache-tomcat-7.0.33\lib\servlet-api.jar;classes -d classes src\com\shan\filter\TestFilter.java

配置程式

在D:\apache-tomcat-7.0.33\webapps檔案夾下建立TestFilter檔案夾,在TestFilter檔案夾下建立WEB-INF目錄,將剛才編譯後的classes檔案夾拷貝到WEB-INF目錄下。將該才建立的test.jsp拷貝到TestFilter檔案夾下。

運行結果

在瀏覽器網址欄輸入localhost:8080/TestFilter/test.jsp,結果如下:

可以看到,在輸出This is a test之前,先執行了doFilter中輸出語句,輸出Before doFilter(),然後調用chain.doFilter(request,response)將請求傳遞給下一個過濾器,因為這之後沒有其他過濾器,所以傳遞給目標資源,輸出This is a test,在響應時又調用了doFilter語句,輸出After doFilter()。

對請求和響應資料進行過濾

在留言板程式中,如果使用者輸入非法字串,則應該對這些字串進行屏蔽。不過HttpServletRequset類並沒有提供對請求資訊進行修改的setXXX()方法,而HttpServletResponse類也沒有提供擷取響應資料的方法,所以雖然過濾器可以截取到請求和響應對象,但是卻無法直接使用這兩個對象對他們的資料繼續替換。不過,在servlet規範中,定義了4個封裝類:ServletRequsetWrapper,ServletResponseWrapper,HttpServletRequsetWrapper,HttpServletReponseWrapper。這4個封裝類分別實現了請求或響應的介面。它們在構造方法中接收真正的請求或響應對象,然後利用該對象的方法來完成自己需要實現的方法。

有了封裝類,要修改請求或響應資訊,就只需要編寫一個封裝類的子類,然後顧飛想要修改的方法即可。例如,我們想要為所有請求添加一個查詢字串,可以編寫一個HttpServletRequestWrapper類的子類,並重寫getQueryString()方法,然後在過濾器的doFilter()方法中,構造這個子類的對象,將其作為參數傳遞給chain.doFilter()方法即可。

對響應內容進行壓縮的過濾器

網站的訪問速度由很多因素決定,包括伺服器效能,網路頻寬,web程式響應速度,伺服器與用戶端網路傳輸速度等。從軟體角度講,我們要提高網站訪問速度,即要儘可能提高web應用程式的執行速度,這可以通過最佳化代碼來實現。如果要進一步提升網頁瀏覽速度,那可以對響應內容進行壓縮,以節省網路的頻寬,提升訪問速度。

目前主流瀏覽器都支援壓縮後的網頁內容,包括gzip,deflate壓縮方式。瀏覽器和web伺服器對於壓縮網頁的通訊過程如下:

1)如果瀏覽器能接受壓縮後的網頁內容,那麼它會在請求中發送Accept-Encoding前序,設定內容為gzip等。

2)web伺服器讀取Accept-Encoding請求前序的值來判斷瀏覽器是否接受壓縮,如果接受,則將目標頁面響應內容進行壓縮後再發送到用戶端,同時設定Content-Encoding實體前序。

3)瀏覽器接收到響應內容後,按照Content-Encoding中的值對響應內容進行解壓縮,然後顯示。

我們可以通過過濾器來對目標頁面的響應內容進行壓縮,該過程類似於對請求和響應內容進行過濾的過濾器。實現原理就是使用封裝類對象替換原始的響應對象,並使用java.util.zip.GZIPOutputStream作為響應內容的輸出資料流對象。

轉載請註明出處:http://blog.csdn.net/iAm333

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.