過濾器能夠動態的攔截請求和響應,以變換或使用包含在請求或響應中的信息。html
過濾器是可用於Servlet編程的Java類,能夠實現如下目的:java
過濾器經過 Web 部署描述符(web.xml)中的 XML 標籤來聲明,而後映射到你的應用程序的部署描述符中的 Servlet 名稱或 URL 模式。web
當 Web 容器啓動 Web 應用程序時,它會爲你在部署描述符中聲明的每個過濾器建立一個實例。spring
Filter的執行順序與在web.xml配置文件中的配置順序一致,通常把Filter配置在全部的Servlet以前。編程
如何編寫過濾器?後端
方法介紹:tomcat
對方法中設計到的類介紹:服務器
Web應用程序能夠根據特定的目的定義若干個不一樣的過濾器,那麼就須要在web.xml中對多個過濾器進行多個配置。而在web.xml中使用<filter-mapping>
來控制多個過濾器的執行順序,即哪一個過濾器的<filter-mapping>
配置在web.xml中的順序排在前面那這個過濾器就先執行。app
實現不一樣的攔截方式須要在中進行不一樣的配置:框架
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWORD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
若在web.xml配置文件中沒有寫出上面四個攔截配置時默認該過濾器只攔截請求。
1.執行目標資源以前作」預處理」工做,例如設置編碼,這種一般都會放行,只是在目標資源執行以前作一些準備工做。(例如:幾乎是全部的Servlet中都須要寫request.setCharacteEncoding()
,能夠把它放入到一個Filter中。)這種過濾器沒有攔截功能。
2.經過條件判斷是否放行,例如校驗當前用戶是否已經登陸,或者用戶IP是否已經被禁用。(有攔截操做) (粗粒度權限控制,會員有會員的權利、遊客有遊客的權利)
3.在目標資源執行後,作一些後續的特殊處理工做。例如把目標資源輸出的數據進行處理。
功能分析:1.統計工做須要在全部資源以前都執行,那麼就能夠放到Filter中了。2.咱們這個過濾器不打算作攔截操做,由於咱們只是用來作統計的。3.用什麼東西來裝載統計的數據。Map,整個網站只須要一個Map便可4.Map何時建立(使用ServletContextListener,在服務器啓動時完成建立,並保存到SevletContext中),Map保存到哪裏:Map須要在Filter中用來保存數據;Map須要在頁面使用,打印Map中的數據。
通常咱們經過jsp頁面請求轉發到servlet時,若請求方式爲POST且請求參數包含中文參數時,咱們須要在servlet的doPost()方法中設置POST請求編碼問題:request.setCharacterEncoding("utf-8");
、設置響應編碼問題:response.setContentType("text/html;charset=utf-8");
,這樣即可以解決post請求即響應編碼問題;而對於GET請求,若傳遞的請求參數包含中文參數時設置請求編碼就比較麻煩,須要在servlet的doGet()方法中設置響應編碼:response.setContentType("text/html;charset=utf-8");
以及請求編碼:首先得到傳遞給servlet的請求參數:String username=request.getParameter("username")
假設傳遞的請求參數爲username
,而後再輸入代碼username=new String(username.getBytes("ISO8859-1"),"utf-8");
,這樣經過jsp頁面轉發到servlet的參數便解決了編碼問題。便可以經過response.getWrite().prinltn(username)
正常顯示在網頁上。
試想:之後的開發中每每會用到不少的servlet,那咱們豈不是要在每個servlet的doPost()和doGet方法中都寫上上述的解決編碼代碼?這時候咱們就能夠經過過濾器來解決了。
首先附上頁面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>$Title$</title> </head> <body> <a href="<c:url value="/AServlet?username=張三"/> ">點擊這裏</a> <form action="<c:url value="/AServlet"/> " method="post"> 用戶名:<input type="text" name="username" value="李四"> <input type="submit" value="提交"> </form> </body> </html> |
經過」點擊這裏」的連接咱們便完成了經過jsp頁面向servlet發送GET請求參數,經過」提交」按鈕咱們便完成了經過jsp頁面向servlet發送POST請求參數。建立一個servlet,咱們在servlet中完成響應參數編碼的問題:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class AServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); } } |
接下來在過濾器中完成請求參數編碼的問題,建立一個過濾器Filter,在web.xml中註冊:
1 2 3 4 5 6 7 8 9 |
<filter> <filter-name>Filter</filter-name> <filter-class>filter.Filter</filter-class> </filter> <filter-mapping> <filter-name>Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> |
Filter中編碼爲:
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Filter implements javax.servlet.Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { } public void init(FilterConfig config) throws ServletException { } } |
對於POST請求參數的編碼設置咱們直接在doFilter()方法體中添加request.setCharacterEncoding("utf-8");
代碼便可(此時運行程序,POST請求參數編碼的問題成功解決),對於GET請求參數的編碼,有些同窗會以爲直接在doFilter()方法體中添加
1 |
String username=request.getParameter("username");username=new String(username.getBytes("ISO-8859-1"),"utf-8"); |
便可。這樣的參數是不太靠譜的,由於這裏咱們知道要傳遞的請求參數爲username因此這裏能夠明瞭的指出,之後咱們不知道請求參數爲何或者請求參數有不少時那就須要更多的上訴代碼,因此這裏咱們採用裝飾者模式對request進行裝飾(即將原本的request換成咱們本身寫的request),建立一個EncodingRequest.java繼承HttpServletRequestWrapper,代碼以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class EncodingRequest extends HttpServletRequestWrapper { private HttpServletRequest req; public EncodingRequest(HttpServletRequest request) { super(request); this.req=request; } @Override public String getParameter(String name) { String value=req.getParameter(name); //處理編碼問題 try { value=new String(value.getBytes("ISO-8859-1"),"utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return value; } } |
在構造方法中,咱們傳入系統的request,而後將這個request賦值給咱們本身編寫的req,而後在重寫的getParameter()方法中經過咱們本身寫的req獲取請求參數並解決編碼問題,而後返回解決完編碼後的參數value(此時這個中文參數已解決編碼),而後在Filer中對咱們本身編寫的request(即Encodingquest對象)放行便可。如今doFilter()方法的方法體爲:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { //處理post請求編碼問題 request.setCharacterEncoding("utf-8"); HttpServletRequest req= (HttpServletRequest) request; /** * 處理get請求的編碼問題 */ // String username=request.getParameter("username"); // username=new String(username.getBytes("ISO-8859-1"),"utf-8"); /** * 調包request * 1.寫一個request的裝飾類 * 2.在放行時,使用咱們本身的request */ EncodingRequest er = new EncodingRequest(req); chain.doFilter(er, response); } |
運行程序,成功解決GET請求方式的編碼問題,可是POST請求方式的編碼又出現了問題,這是爲何呢?由於咱們在doFilter方法中已經經過代碼request.setCharacterEncoding("utf-8");
處理了POST請求方式的編碼問題,可是此時的請求是系統的request對象而不是咱們本身寫的req,咱們對req進行了放行而沒有對request進行方式,因此方法體中應該增長if判斷語句,改正後的doFilter()方法體內容爲:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { //處理post請求編碼問題 request.setCharacterEncoding("utf-8"); HttpServletRequest req= (HttpServletRequest) request; /** * 處理get請求的編碼問題 */ // String username=request.getParameter("username"); // username=new String(username.getBytes("ISO-8859-1"),"utf-8"); /** * 調包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); } } |
此時運行程序,成功解決POST請求方式和GET請求方式的編碼問題。在學習框架以前咱們都這樣經過Filter解決編碼問題,而當咱們學習了Spring MVC框架後咱們處理POST請求參數的編碼問題時直接在web.xml中添加以下配置而不用再寫一個過濾器:
1 2 3 4 5 6 7 8 9 10 11 12 |
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> |
解決GET請求方式的編碼問題時有兩種解決方法:1.修改tomcat配置文件添加編碼與工程編碼一致,以下:
1 |
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/> |
2.對參數進行從新編碼:
1 2 |
String userName new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8") |
第二種方法須要對每一個參數都進行從新編碼,比較麻煩。
迴歸咱們的過濾器講解,經過如上包裝request的方式即可以經過過濾器解決全站編碼問題。