閱讀目錄
過濾器是Java Web三大組件之一,它與Servlet很相似。對於Web應用程序來說,過濾器是一個駐留在服務器端的Web組件,它可以截取客戶端和資源之間的請求和響應信息並對這些信息進行過濾。本文將對過濾器的和實現機制和應用進行簡單的總結。
當Web容器接收到一個對資源的請求時,它將判斷是否有過濾器與這個資源相關聯,如果有那麼容器將請求交給過濾器進行處理。下圖所示為過濾器的工作過程。
在web應用程序中可以部署多個過濾器形成一個過濾器鏈,在請求資源時,過濾器鏈中的過濾器將依次對請求進行處理(執行順序是在web.xml文件中的部署順序),並將請求傳遞給下一個過濾器,直到目標資源。在發送響應時,則是按照相反的順序對響應進行處理的,直到客戶端。
過濾器的應用場景主要有幾下幾點:
寫一個過濾器就是寫一個類,並且這個類要實現Filter接口。Filter接口定義了三個方法,init()、doFilter()和destory()。它們的執行構成了過濾器的生命周期。
下面代碼既是一個實現了Filter接口的過濾器:
public class FilterDemo1 implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { response.setContentType("text/html;charset=GB2312"); PrintWriter out=response.getWriter(); out.println("過濾器攔截你!"); chain.doFilter(request, response); out.close(); } public void destroy() { } }
過濾器寫好之後要通過在web.xml文件對其進行配置,配置的方法類似於Servlet的。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>day_0701</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <filter> <filter-name>FilterDemo1</filter-name> <filter-class>com.test.filter.FilterDemo1</filter-class> </filter> <filter-mapping> <filter-name>FilterDemo1</filter-name> <url-pattern>/1.jsp</url-pattern> </filter-mapping> </web-app>
然後在WebContent目錄下,新建一個jsp文件:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>在此處插入標題</title> </head> <body> 這是測試頁面! </body> </html>
當請求訪問1.jsp文件時,顯示結果如下:
結果分析:因為上述過濾器是與1.jsp文件相關聯,所以web容器將請求先交給過濾器進行處理,輸出“過濾器攔截你”後,過濾器對請求進行“放行”,所以又輸出“這是測試頁面”。
過濾器的部署是在<filter>和<filter-mapping>元素來完成的。
過濾器有四種攔截方式,分別是:REQUEST、FORWARD、INCLUDE、ERROR。
攔截方式是在<dispatcher></dispatcher>中設置的,默認情況是REQUEST方式。
可以通過<url-pattern>或者<servlet-name>中設置目標資源,在<url-pattern>中指定過濾器關聯的URL樣式;在<servlet-name>指定過濾器指定的Servlet,用戶在訪問<url-pattern>元素指定的URL上的資源或<servlet-name>元素指定的Servlet時,該過濾器才會被容器調用。
<filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/2.jsp</url-pattern> <servlet-name>DemoServlet</servlet-name> </filter-mapping>
通過過濾器可以解決頁面的亂碼問題,代碼如下:
public class EncodingFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 處理post請求編碼問題 request.setCharacterEncoding("utf-8"); HttpServletRequest req = (HttpServletRequest) request; /* * 處理GET請求的編碼問題 * 調包request * 1. 寫一個request的裝飾類 * 2. 在放行時,使用我們自己的request */ if(req.getMethod().equals("GET")) { EncodingRequest er = new EncodingRequest(req); chain.doFilter(er, response); } else if(req.getMethod().equals("POST")) { chain.doFilter(request, response); } } public void init(FilterConfig fConfig) throws ServletException { } }
/** * 裝飾reqeust */ public class EncodingRequest extends HttpServletRequestWrapper { private HttpServletRequest req; public EncodingRequest(HttpServletRequest request) { super(request); this.req = request; } public String getParameter(String name) { String value = req.getParameter(name); // 處理編碼問題 try { value = new String(value.getBytes("iso-8859-1"), "utf-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } return value; } }