日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Servlet 过滤器

發(fā)布時間:2024/9/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Servlet 过滤器 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、Filter 概述

Filter 也稱之為過濾器,它是Servlet 技術(shù)中很實用的一個知識點,Web 開發(fā)人員通過Filter 技術(shù),對Web 服務(wù)器管理的所有Web 資源:例如Jsp, Servlet, 靜態(tài)圖片文件或靜態(tài) html 文件等進行攔截,從而實現(xiàn)一些特殊的功能。例如實現(xiàn)URL 級別的權(quán)限訪問控制、過濾敏感詞匯、壓縮響應(yīng)信息等一些高級功能。

Servlet API中提供了一個Filter 接口,開發(fā)Web 應(yīng)用時,如果編寫的Java 類實現(xiàn)了這個接口,則把這個Java 類稱之為過濾器Filter。通過Filte r技術(shù),開發(fā)人員可以實現(xiàn)用戶在訪問某個目標資源之前,對訪問的請求和響應(yīng)進行攔截。

1.1實現(xiàn)過濾器的步驟

  • 寫一個類實現(xiàn)特定的接口Filter
  • 在web .xml 中注冊該過濾器
  • 在配置過濾器的時候有點類似在web .xml 中配置Servlet。主要相關(guān)配置如下

    <filter><filter-name>Demo1Filter</filter-name> <!-- 給過濾器起名字--><filter-class>com.jas.filter.Filter1</filter-class> <!-- 過濾器的處理類--></filter><!-- 一個Filter可以配置多個filter-mapping--><filter-mapping> <filter-name>Demo1Filter</filter-name> <!-- 指定上面過濾器的名字--><!-- 一個Filtermapping中可以配置多個url-partten--> <url-pattern>/servlet/Demo1Servlet</url-pattern><url-pattern>/servlet/*</url-pattern><url-pattern>/*</url-pattern><servlet-name>DemoServlet</servlet-name> <!-- 具體要攔截哪一個Servlet--></filter-mapping>

    二、Filter 接口中相關(guān)方法介紹

    接口Filter 中一共提供了三個方法,分別是:
    init(FilterConfig filterConfig)、
    doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 、
    destroy()。

    2.1init 方法

    這個方法中允許接收一個FilterConfig 對象,可以通過這個對象獲得在web.xml 中配置當前過濾器的初始化配置信息。

    <!-- 可以配置當前過濾器的初始化信息,可以配置多個,在Filter中利用FilterConfig對象來獲取--> <init-param><param-name>name1</param-name><param-value>value1</param-value> </init-param>

    2.2doFilter 方法

    這個方法中接收了三個參數(shù),分別是request、response和chain。前兩個參數(shù)大家都比較熟悉這里就不再做具體介紹。主要介紹一下FilterChain 對象。

    FilterChain : 代表過濾器鏈的對象
    一個資源可能被多個過濾器所攔截到,攔截的順序和過濾器在web.xml 中filter-mapping 的配置順序相同。 所有對當前資源訪問進行攔截的過濾器按照攔截順序就組成了一個過濾器鏈。這個過濾器鏈的最后一個節(jié)點是要訪問的資源。FilterChain 提供了doFilter 方法,這個方法一旦被調(diào)用就表明當前過濾器沒有問題了,直接放行,請求執(zhí)行過濾器鏈的下一個節(jié)點,如果下一個節(jié)點是資源則直接訪問該資源。

    2.3destroy 方法

    這個方法沒有什么需要特別注意的地方。在過濾器對象銷毀之前,執(zhí)行相應(yīng)的操作。

    2.4過濾器的生命周期

  • 當服務(wù)器啟動時,Web 應(yīng)用加載后,立即創(chuàng)建這個Web 應(yīng)用中的所有的過濾器,過濾器創(chuàng)建出來后立即調(diào)用init 方法執(zhí)行初始化的操作。
  • 創(chuàng)建出來后一直駐留在內(nèi)存中為后續(xù)的攔截進行服務(wù),每次攔截到請求后都會調(diào)用doFilter 方法。
  • 在服務(wù)器關(guān)閉或Web 應(yīng)用被移除出容器時,隨著Web 應(yīng)用的銷毀,過濾器對象銷毀。銷毀之前調(diào)用destory方法。
  • 三、多個過濾器的執(zhí)行順序

    3.1示例

    通過上面的了解我們知道,當配置多個過濾器時,會構(gòu)成一個過濾器鏈,該過濾器鏈的最后一個節(jié)點代表要訪問的資源,過濾器的執(zhí)行順序是在web.xml 中filter-mapping 中配置的順序。下面就來通過一個具體例子來實踐一下

    Filter1

    package com.jas.filter;import javax.servlet.*; import java.io.IOException;public class Filter1 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("過濾器1 前");chain.doFilter(request,response); //放行到下一個過濾器或要訪問的資源System.out.println("過濾器1 后");}@Overridepublic void destroy() {} }

    Filter2

    package com.jas.filter;import javax.servlet.*; import java.io.IOException;public class Filter2 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("過濾器2 前");chain.doFilter(request,response);System.out.println("過濾器2 后");}@Overridepublic void destroy() {} }

    在web.xml 中注冊這兩個過濾器

    <filter><filter-name>filter1</filter-name><filter-class>com.jas.filter.Filter1</filter-class></filter><filter><filter-name>filter2</filter-name><filter-class>com.jas.filter.Filter2</filter-class></filter><!-- 配置的順序:filter1 - > filter2 --><filter-mapping><filter-name>filter1</filter-name><url-pattern>/*</url-pattern> <!-- 攔截所有請求REQUEST--></filter-mapping><filter-mapping><filter-name>filter2</filter-name><url-pattern>/*</url-pattern></filter-mapping>

    index.jsp(在控制臺輸出一句話)

    <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html><head><title>$Title$</title></head><body><% System.out.println("要訪問的資源");%> </body> </html>

    在訪問index.jsp 后,控制臺輸出如下

    過濾器1 前 過濾器2 前 要訪問的資源 過濾器2 后 過濾器1 后

    3.2總結(jié)

    對于有多個過濾器攔截的資源,在訪問時會按照web.xml 中的filter-mapping的 配置順序執(zhí)行,
    在執(zhí)行完 chain.doFilter(request,response) 之后(放行),下面的代碼并不會立即執(zhí)行,
    而是在對資源訪問結(jié)束后,再返回來執(zhí)行 chain.doFilter(request,response) 下的動作,
    這個執(zhí)行順序和過濾器的執(zhí)行順序是相反的。

    四、過濾器應(yīng)用之解決請求亂碼

    4.1Servlet 請求與響應(yīng)亂碼總結(jié)

    PS:Tomcat 默認的編碼格式是“iso8859-1”,瀏覽器一般是”utf-8”。

    響應(yīng)亂碼
    之所以有亂碼的出現(xiàn),是因為服務(wù)器對輸出數(shù)據(jù)的編碼與瀏覽器端對數(shù)據(jù)的解碼使用的不是同一個編碼格式。

    解決方式一:

    response.setCharacterEncoding("utf-8"); //指定服務(wù)器對輸出數(shù)據(jù)的編碼使用“utf-8” response.setContentType("text/html;charset=utf-8"); //指定客戶端瀏覽器對數(shù)據(jù)的解碼使用“utf-8”

    解決方式二:

    response.setContentTye("text/html;charset=utf-8"); //即指定服務(wù)器的編碼格式也指定瀏覽器的解碼格式

    請求亂碼
    請求亂碼的出現(xiàn)是因為服務(wù)端對客戶端發(fā)送的數(shù)據(jù)的解碼格式與客戶端編碼格式不一致造成的。由于客戶端發(fā)送數(shù)據(jù)的方式主要是GET 與 POST 方式,所以對應(yīng)的亂碼解決方式也不一樣。

    對于POST 方式提交的數(shù)據(jù)的解決方式:

    request.setCharacterEncoding("utf-8"); //明確告知服務(wù)器以瀏覽器的編碼格式來處理數(shù)據(jù)

    對于GET 方式提交的數(shù)據(jù)的解決方式:

    String username = request.getParameter("username"); //對于GET 方式提交的數(shù)據(jù),不能通過上面的方式解決亂碼,只能手動對數(shù)據(jù)進行編解碼 //先按照服務(wù)器的編碼格式對數(shù)據(jù)進行編碼,編碼回原來的二進制文件,接著再以客戶端的編碼格式utf-8“”對數(shù)據(jù)進行解析 username = new String(username.getBytes("iso8859-1"),"utf-8");

    過濾器解決請求亂碼

    針對上面關(guān)于GET 方式與POST 方式提交數(shù)據(jù)的方式以及解決亂碼的方式,我們在每個Servlet 里都需要對請求的參數(shù)進行編解碼。在了解過濾器之后,我們就可以在訪問Servlet 之前對編解碼格式進行統(tǒng)一的指定,這樣就不用在Servlet 里寫編解碼格式的代碼了。

    過濾器類EncodingFilter

    package com.jas.filter;import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.IOException; import java.util.Map;public class EncodingFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {chain.doFilter(new MyHttpServletRequest((HttpServletRequest) request),response);}@Overridepublic void destroy() { } }//HttpServletRequestWrapper 本身是HttpServletRequest 的裝飾類 class MyHttpServletRequest extends HttpServletRequestWrapper {private HttpServletRequest request = null;private boolean flag = true;public MyHttpServletRequest(HttpServletRequest request) {super(request);this.request = request;}@Overridepublic Map<String, String[]> getParameterMap() {try {if (request.getMethod().equalsIgnoreCase("post")) { //處理post表單提交亂碼request.setCharacterEncoding("utf-8");return this.request.getParameterMap();} else if (request.getMethod().equalsIgnoreCase("get")) { //處理get方式請求的亂碼Map<String, String[]> map = this.request.getParameterMap(); //請求信息組成的mapif (flag) { //循環(huán)遍歷參數(shù)map進行轉(zhuǎn)碼for (Map.Entry<String, String[]> entry : map.entrySet()) {String[] value = entry.getValue();for (int i = 0; i < value.length; i++) {//進行手動的編解碼value[i] = new String(value[i].getBytes("iso8859-1"), "utf-8");}}}flag = false; //避免解碼正確后再進行解碼,出現(xiàn)亂碼return map;} else { //對于其他方式提交的數(shù)據(jù)不做處理 -> 一般是GET 與 POSTreturn request.getParameterMap();}} catch (Exception e) {e.printStackTrace();}return null;}@Overridepublic String getParameter(String name) {return getParameterValues(name)[0] == null ? null : getParameterValues(name)[0];}@Overridepublic String[] getParameterValues(String name) {return getParameterMap().get(name);} }

    在web.xml 中注冊該過濾器

    <filter><filter-name>encodingFilter</filter-name><filter-class>com.jas.filter.EncodingFilter</filter-class></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

    (完)

    總結(jié)

    以上是生活随笔為你收集整理的Servlet 过滤器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。