Servlet 过滤器
一、Filter 概述
Filter 也稱之為過濾器,它是Servlet 技術中很實用的一個知識點,Web 開發人員通過Filter 技術,對Web 服務器管理的所有Web 資源:例如Jsp, Servlet, 靜態圖片文件或靜態 html 文件等進行攔截,從而實現一些特殊的功能。例如實現URL 級別的權限訪問控制、過濾敏感詞匯、壓縮響應信息等一些高級功能。
Servlet API中提供了一個Filter 接口,開發Web 應用時,如果編寫的Java 類實現了這個接口,則把這個Java 類稱之為過濾器Filter。通過Filte r技術,開發人員可以實現用戶在訪問某個目標資源之前,對訪問的請求和響應進行攔截。
1.1實現過濾器的步驟
在配置過濾器的時候有點類似在web .xml 中配置Servlet。主要相關配置如下
<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 接口中相關方法介紹
接口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 方法
這個方法中接收了三個參數,分別是request、response和chain。前兩個參數大家都比較熟悉這里就不再做具體介紹。主要介紹一下FilterChain 對象。
FilterChain : 代表過濾器鏈的對象
一個資源可能被多個過濾器所攔截到,攔截的順序和過濾器在web.xml 中filter-mapping 的配置順序相同。 所有對當前資源訪問進行攔截的過濾器按照攔截順序就組成了一個過濾器鏈。這個過濾器鏈的最后一個節點是要訪問的資源。FilterChain 提供了doFilter 方法,這個方法一旦被調用就表明當前過濾器沒有問題了,直接放行,請求執行過濾器鏈的下一個節點,如果下一個節點是資源則直接訪問該資源。
2.3destroy 方法
這個方法沒有什么需要特別注意的地方。在過濾器對象銷毀之前,執行相應的操作。
2.4過濾器的生命周期
三、多個過濾器的執行順序
3.1示例
通過上面的了解我們知道,當配置多個過濾器時,會構成一個過濾器鏈,該過濾器鏈的最后一個節點代表要訪問的資源,過濾器的執行順序是在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總結
對于有多個過濾器攔截的資源,在訪問時會按照web.xml 中的filter-mapping的 配置順序執行,
在執行完 chain.doFilter(request,response) 之后(放行),下面的代碼并不會立即執行,
而是在對資源訪問結束后,再返回來執行 chain.doFilter(request,response) 下的動作,
這個執行順序和過濾器的執行順序是相反的。
四、過濾器應用之解決請求亂碼
4.1Servlet 請求與響應亂碼總結
PS:Tomcat 默認的編碼格式是“iso8859-1”,瀏覽器一般是”utf-8”。
響應亂碼
之所以有亂碼的出現,是因為服務器對輸出數據的編碼與瀏覽器端對數據的解碼使用的不是同一個編碼格式。
解決方式一:
response.setCharacterEncoding("utf-8"); //指定服務器對輸出數據的編碼使用“utf-8” response.setContentType("text/html;charset=utf-8"); //指定客戶端瀏覽器對數據的解碼使用“utf-8”解決方式二:
response.setContentTye("text/html;charset=utf-8"); //即指定服務器的編碼格式也指定瀏覽器的解碼格式請求亂碼
請求亂碼的出現是因為服務端對客戶端發送的數據的解碼格式與客戶端編碼格式不一致造成的。由于客戶端發送數據的方式主要是GET 與 POST 方式,所以對應的亂碼解決方式也不一樣。
對于POST 方式提交的數據的解決方式:
request.setCharacterEncoding("utf-8"); //明確告知服務器以瀏覽器的編碼格式來處理數據對于GET 方式提交的數據的解決方式:
String username = request.getParameter("username"); //對于GET 方式提交的數據,不能通過上面的方式解決亂碼,只能手動對數據進行編解碼 //先按照服務器的編碼格式對數據進行編碼,編碼回原來的二進制文件,接著再以客戶端的編碼格式utf-8“”對數據進行解析 username = new String(username.getBytes("iso8859-1"),"utf-8");過濾器解決請求亂碼
針對上面關于GET 方式與POST 方式提交數據的方式以及解決亂碼的方式,我們在每個Servlet 里都需要對請求的參數進行編解碼。在了解過濾器之后,我們就可以在訪問Servlet 之前對編解碼格式進行統一的指定,這樣就不用在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) { //循環遍歷參數map進行轉碼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; //避免解碼正確后再進行解碼,出現亂碼return map;} else { //對于其他方式提交的數據不做處理 -> 一般是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>(完)
總結
以上是生活随笔為你收集整理的Servlet 过滤器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: u盘插电脑里怎么打开 U盘如何在电脑上打
- 下一篇: 鹤岗市7月份烟草情况?7月份烟草