1监嗜、Filter介紹
Filter技術(shù)是servlet 2.3新增加的功能呜投。servlet2.3是sun公司于2000年10月發(fā)布的青自,它的開發(fā)者包括許多個人和公司團(tuán)體崖瞭,充分體現(xiàn)了sun公司所倡導(dǎo)的代碼開放性原則统屈。在眾多參與者的共同努力下胚吁,servlet2.3比以往功能都強大了許多,而且性能也有了大幅提高鸿吆。
通過Filter功能囤采,用戶可以改變一個request和修改一個response。Filter不是一個servlet惩淳,它不能產(chǎn)生一個response蕉毯,但是,它能夠在一個request到達(dá)servlet之前預(yù)處理request思犁,也可以在response離開servlet時處理response代虾。
這樣,F(xiàn)ilter可以對所有的發(fā)往Java服務(wù)器的請求(包括對html激蹲,js棉磨,圖片等靜態(tài)資源的請求)做攔截,從而實現(xiàn)一些特殊的功能学辱,如URL級別的權(quán)限訪問控制乘瓤、過濾敏感詞匯、壓縮響應(yīng)信息等策泣。
2衙傀、Filter執(zhí)行機(jī)制
Servlet API中提供了一個Filter接口,開發(fā)web應(yīng)用時萨咕,如果編寫的Java類實現(xiàn)了這個接口,則把這個java類稱之為過濾器Filter危队。通過Filter類聪建,可以實現(xiàn)用戶在訪問某個目標(biāo)資源之前,對訪問的請求和響應(yīng)進(jìn)行攔截茫陆。
Filter接口中有方法void doFilter(ServletRequest req,ServletResponse res,FilterChain chain)
用來執(zhí)行filter的工作金麸。每一個filter從doFilter()
方法中得到當(dāng)前的request及response對象。在這個方法里盅弛,可以進(jìn)行任何的針對request及response的操作钱骂,包括收集數(shù)據(jù)叔锐,包裝數(shù)據(jù)等。filter調(diào)用chain.doFilter()
方法將請求從該filter中放行见秽。之后愉烙,有可能請求到了要訪問的資源對象,也有可能把控制權(quán)交給了下一個filter解取。
當(dāng)我們編寫好Filter步责,并配置對哪個web資源進(jìn)行攔截后,WEB服務(wù)器每次在調(diào)用web資源的service方法之前禀苦,都會先調(diào)用一下filter的doFilter方法蔓肯,因此,在該方法內(nèi)編寫代碼可達(dá)到如下目的:
- 調(diào)用目標(biāo)資源之前振乏,讓一段代碼執(zhí)行蔗包。
- 是否調(diào)用目標(biāo)資源(即是否讓用戶訪問web資源)。
- 調(diào)用目標(biāo)資源之后慧邮,讓一段代碼執(zhí)行调限。
web服務(wù)器在調(diào)用doFilter方法時,會傳遞一個filterChain對象進(jìn)來误澳,filterChain對象是filter接口中最重要的一個對象耻矮,它也提供了一個doFilter方法,開發(fā)人員可以根據(jù)需求決定是否調(diào)用此方法忆谓,調(diào)用該方法裆装,則web服務(wù)器就會調(diào)用web資源的service方法,即web資源就會被訪問倡缠,否則web資源不會被訪問哨免。
3、Filter入門示意
這里我們編寫一個簡單的Filter示意代碼昙沦。
首先铁瞒,新建一個Filter類,實現(xiàn)javax.servlet.Filter
接口桅滋。
com.lfqy.web.filter.FilterTrial01
:
package com.lfqy.web.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Created by chengxia on 2019/11/4.
* filter的三種典型應(yīng)用:
1、可以在filter中根據(jù)條件決定是否調(diào)用chain.doFilter(request, response)方法身辨,即是否讓目標(biāo)資源執(zhí)行
2丐谋、在讓目標(biāo)資源執(zhí)行之前,可以對request\response作預(yù)處理煌珊,再讓目標(biāo)資源執(zhí)行
3号俐、在目標(biāo)資源執(zhí)行之后,可以捕獲目標(biāo)資源的執(zhí)行結(jié)果定庵,從而實現(xiàn)一些特殊的功能
*/
public class FilterTrial01 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("The filter is initializing...");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//設(shè)置request和response的編碼格式
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
//設(shè)置請求的contenttype
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("Before the request is handled...");
System.out.println("url: " + ((HttpServletRequest)servletRequest).getRequestURL());
//讓目標(biāo)資源執(zhí)行吏饿,放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("After the request is handled...");
}
@Override
public void destroy() {
System.out.println("The filter is destroying...");
}
}
在這個filter的實現(xiàn)類中踪危,在請求的執(zhí)行前后,分別輸出提示信息和請求的url到控制臺猪落。
然后贞远,在配置文件中,添加這個filter的定義笨忌。
WEB-INF/web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>FilterTrial01</filter-name>
<filter-class>com.lfqy.web.filter.FilterTrial01</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTrial01</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.html</url-pattern>
</filter-mapping>
</web-app>
從這個配置文件的內(nèi)容蓝仲,可以看出,filter的配置分為兩部分:一部分是定義filter的名稱和filter實現(xiàn)類的關(guān)聯(lián)關(guān)系官疲,另外一部分是定義filter所攔截請求的過濾規(guī)則袱结。這里我們配置了兩個請求url的攔截規(guī)則,也就是攔截所有對jsp和html頁面的請求(前面已經(jīng)說明filter可以攔截對靜態(tài)資源的請求)途凫。前一部分我們稱為注冊Filter垢夹,后一部分我們稱為映射Filter。
這里需要注意urlpattern的配置規(guī)則:
- 以
/
開頭和以/*
結(jié)尾的是用來做路徑映射的维费。 - 以前綴
*.
開頭的是用來做擴(kuò)展映射的果元。 -
/
是用來定義default servlet映射的。 - 剩下的都是用來定義詳細(xì)映射的掩完。比如:
/aa/bb/cc.jsp
所以噪漾,如果urlpattern配置成/*.jsp
會報錯,因為它既屬于路徑映射且蓬,又屬于后綴映射欣硼,應(yīng)用服務(wù)器會困惑。
最后恶阴,編寫兩個測試頁面诈胜。
index.jsp
:
<%--
Created by IntelliJ IDEA.
User: chengxia
Date: 2019/11/4
Time: 7:47 AM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Trial Page for Filter</title>
</head>
<body>
<h3>This is a filter page.</h3>
</body>
</html>
test.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Gogogo</title>
</head>
<body>
<h1>gogogo</h1>
</body>
</html>
這樣,啟動服務(wù)器之后冯事,分別訪問http://localhost:8080/test.html
和http://localhost:8080/index.jsp
焦匈,可以看到控制臺輸出如下:
Before the request is handled...
url: http://localhost:8080/test.html
After the request is handled...
Before the request is handled...
url: http://localhost:8080/index.jsp
After the request is handled...
4、Filter其它說明
4.1 Filter鏈
在一個web應(yīng)用中昵仅,可以開發(fā)編寫多個Filter缓熟,這些Filter組合起來稱之為一個Filter鏈。
web服務(wù)器根據(jù)Filter在web.xml
文件中的注冊順序摔笤,決定先調(diào)用哪個Filter够滑,當(dāng)?shù)谝粋€Filter的doFilter方法被調(diào)用時,web服務(wù)器會創(chuàng)建一個代表Filter鏈的FilterChain對象傳遞給該方法吕世。在doFilter方法中彰触,開發(fā)人員如果調(diào)用了FilterChain對象的doFilter方法,則web服務(wù)器會檢查FilterChain對象中是否還有filter命辖,如果有况毅,則調(diào)用第2個filter分蓖,如果沒有,則調(diào)用目標(biāo)資源尔许。
4.2 Filter生命周期
4.2.1 創(chuàng)建
Filter的創(chuàng)建和銷毀由應(yīng)用服務(wù)器負(fù)責(zé)么鹤。 web應(yīng)用啟動時,應(yīng)用服務(wù)器將創(chuàng)建Filter的實例對象母债,并調(diào)用其init方法午磁,完成對象的初始化功能,從而為后續(xù)的用戶請求作好攔截的準(zhǔn)備工作毡们,filter對象只會創(chuàng)建一次迅皇,init方法也只會執(zhí)行一次。通過init方法的參數(shù)衙熔,可獲得代表當(dāng)前filter配置信息的FilterConfig對象登颓。
4.2.2 銷毀
Web容器調(diào)用destroy方法銷毀Filter。destroy方法在Filter的生命周期中僅執(zhí)行一次红氯。在destroy方法中框咙,可以釋放過濾器使用的資源。
4.2.3 FilterConfig接口
用戶在配置filter時痢甘,可以使用<init-param>
為filter配置一些初始化參數(shù)喇嘱,當(dāng)web容器實例化Filter對象,調(diào)用其init方法時塞栅,會把封裝了filter初始化參數(shù)的filterConfig對象傳遞進(jìn)來者铜。因此開發(fā)人員在編寫filter時,通過filterConfig對象的方法放椰,就可獲得:
-
String getFilterName()
:得到filter的名稱作烟。 -
String getInitParameter(String name)
: 返回在部署描述中指定名稱的初始化參數(shù)的值。如果不存在返回null. -
Enumeration getInitParameterNames()
:返回過濾器的所有初始化參數(shù)的名字的枚舉集合砾医。 -
public ServletContext getServletContext()
:返回Servlet上下文對象的引用拿撩。
如下是一個帶參數(shù)的filter的例子。
com.lfqy.web.filter.FilterInitParamTrial
:
package com.lfqy.web.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Created by chengxia on 2019/11/4.
* filter的三種典型應(yīng)用:
1如蚜、可以在filter中根據(jù)條件決定是否調(diào)用chain.doFilter(request, response)方法压恒,即是否讓目標(biāo)資源執(zhí)行
2、在讓目標(biāo)資源執(zhí)行之前错邦,可以對request\response作預(yù)處理涎显,再讓目標(biāo)資源執(zhí)行
3、在目標(biāo)資源執(zhí)行之后兴猩,可以捕獲目標(biāo)資源的執(zhí)行結(jié)果,從而實現(xiàn)一些特殊的功能
*/
public class FilterInitParamTrial implements Filter {
private String filterName;
private String filterFunc;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("The filter is initializing...");
filterName = filterConfig.getInitParameter("FilterName");
filterFunc = filterConfig.getInitParameter("Function");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//設(shè)置request和response的編碼格式
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
//設(shè)置請求的contenttype
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println(filterName + " for function " + filterFunc + "executing. Before the request is handled...");
System.out.println("url: " + ((HttpServletRequest)servletRequest).getRequestURL());
//讓目標(biāo)資源執(zhí)行早歇,放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println(filterName + " for function " + filterFunc + "executing. After the request is handled...");
}
@Override
public void destroy() {
System.out.println("The filter is destroying...");
}
}
WEB-INF/web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>FilterTrial01</filter-name>
<filter-class>com.lfqy.web.filter.FilterTrial01</filter-class>
</filter>
<filter>
<filter-name>FilterInitParamTrial</filter-name>
<filter-class>com.lfqy.web.filter.FilterInitParamTrial</filter-class>
<init-param>
<description>測試Filter配置參數(shù)01</description>
<param-name>FilterName</param-name>
<param-value>PaopaoFilter</param-value>
</init-param>
<init-param>
<description>測試Filter配置參數(shù)02</description>
<param-name>Function</param-name>
<param-value>Test filter init param...</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FilterTrial01</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>FilterInitParamTrial</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.html</url-pattern>
</filter-mapping>
</web-app>
重啟tomcat服務(wù)器倾芝,配置生效之后讨勤,訪問http://localhost:8080/test.html
,控制臺輸出如下:
PaopaoFilter for function Test filter init param...executing. Before the request is handled...
url: http://localhost:8080/test.html
PaopaoFilter for function Test filter init param...executing. After the request is handled...
可見晨另,過濾器中配置的初始參數(shù)已經(jīng)被拿到潭千。
4.3 映射Filter時的dispatcher屬性
<dispatcher>指定過濾器所攔截的資源被 Servlet 容器調(diào)用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一借尿,默認(rèn)REQUEST刨晴。用戶可以設(shè)置多個<dispatcher> 子元素用來指定 Filter 對資源的多種調(diào)用方式進(jìn)行攔截。如下:
<filter-name>filterName</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<dispatcher>
子元素可以設(shè)置的值及其意義:
- REQUEST:當(dāng)用戶直接訪問頁面時路翻,Web容器將會調(diào)用過濾器狈癞。如果目標(biāo)資源是通過RequestDispatcher的
include()
或forward()
方法訪問時,那么該過濾器就不會被調(diào)用茂契。 - INCLUDE:如果目標(biāo)資源是通過RequestDispatcher的
include()
方法訪問時蝶桶,那么該過濾器將被調(diào)用。除此之外掉冶,該過濾器不會被調(diào)用真竖。 - FORWARD:如果目標(biāo)資源是通過RequestDispatcher的
forward()
方法訪問時,那么該過濾器將被調(diào)用厌小,除此之外恢共,該過濾器不會被調(diào)用。 - ERROR:如果目標(biāo)資源是通過聲明式異常處理機(jī)制調(diào)用時璧亚,那么該過濾器將被調(diào)用讨韭。除此之外,過濾器不會被調(diào)用涨岁。
5拐袜、Filter使用場景示例
5.1 裝飾器模式
5.1.1 定義
裝飾器模式,又名包裝(Wrapper)模式梢薪。裝飾模式以對客戶端透明的方式擴(kuò)展對象的功能蹬铺,是繼承關(guān)系的一個替代方案。裝飾模式是在不必改變原類文件和使用繼承的情況下秉撇,動態(tài)的擴(kuò)展一個對象的功能甜攀。在裝飾器模式中,會創(chuàng)建一個包裝對象琐馆,用來裝飾包裹真實的對象规阀。
5.1.2 使用場景說明
當(dāng)某個對象的方法不適應(yīng)業(yè)務(wù)需求時,通常有2種方式可以對方法進(jìn)行增強:
- 編寫子類瘦麸,覆蓋需增強的方法谁撼。
- 使用裝飾器設(shè)計模式對方法進(jìn)行增強。
在實際應(yīng)用中遇到需增強對象的方法時滋饲,到底選用哪種方式比較好呢厉碟?這個沒有具體的定式喊巍,只能是根據(jù)具體的需求來采用具體的方式,不過有一種情況下箍鼓,必須使用Decorator設(shè)計模式:即被增強的對象崭参,開發(fā)人員只能得到它的對象,無法得到它的class文件款咖。比如request何暮、response對象,開發(fā)人員之所以在servlet中能通過sun公司定義的HttpServletRequest\response接口去操作這些對象铐殃,是因為Tomcat服務(wù)器廠商編寫了request海洼、response接口的實現(xiàn)類。web服務(wù)器在調(diào)用servlet時背稼,會用這些接口的實現(xiàn)類創(chuàng)建出對象贰军,然后傳遞給servlet程序。此種情況下蟹肘,由于開發(fā)人員根本不知道服務(wù)器廠商編寫的request词疼、response接口的實現(xiàn)類是哪個?在程序中只能拿到服務(wù)器廠商提供的對象帘腹,因此就只能采用Decorator設(shè)計模式對這些對象進(jìn)行增強贰盗。
5.1.3 裝飾器模式的實現(xiàn)
在實現(xiàn)裝飾器模式時铛漓,首先看需要被增強對象繼承了什么接口或父類儒飒,編寫一個類也去繼承這些接口或父類。然后驮宴,在類中定義一個變量球化,變量類型即需增強對象的類型秽晚,同時,在類中定義一個構(gòu)造函數(shù)筒愚,構(gòu)造函數(shù)的參數(shù)是需增強的對象赴蝇。最后,覆蓋需增強的方法巢掺,編寫增強的代碼句伶。
這里需要注意,裝飾器模式中陆淀,必須重新編寫接口或者父類的所有方法考余。對于其中,根本不需要增強的方法轧苫,只需要簡單調(diào)用被增強對象(裝飾器類中的成員變量)的同名方法即可楚堤。
5.2 Servlet API中對于請求對象和響應(yīng)對象的默認(rèn)裝飾器實現(xiàn)
Servlet API中提供了一個request對象的Decorator設(shè)計模式的默認(rèn)實現(xiàn)類HttpServletRequestWrapper,HttpServletRequestWrapper類實現(xiàn)了request接口中的所有方法,但這些方法的內(nèi)部實現(xiàn)都是僅僅調(diào)用了一下所包裝的的 request對象的對應(yīng)方法身冬,以避免用戶在對request對象進(jìn)行增強時需要實現(xiàn)request接口中的所有方法鳄袍。
Servlet API中也提供了response對象的Decorator設(shè)計模式的默認(rèn)實現(xiàn)類HttpServletResponseWrapper,HttpServletResponseWrapper類實現(xiàn)了response接口中的所有方法吏恭,但這些方法的內(nèi)部實現(xiàn)都是僅僅調(diào)用了一下所包裝的的 response對象的對應(yīng)方法,以避免用戶在對response對象進(jìn)行增強時需要實現(xiàn)response接口中的所有方法重罪。
這兩個現(xiàn)成的裝飾器類中樱哼,都定義了各自的包裝對象,實現(xiàn)了request對象和reponse對象對應(yīng)接口的方法剿配。只不過在方法的實現(xiàn)中搅幅,都是簡單調(diào)用對應(yīng)包裝對象的方法。這樣的好處是呼胚,當(dāng)我們自己實現(xiàn)裝飾器類的時候茄唐,只需要繼承這兩個線程的裝飾器類,然后蝇更,重寫我們想擴(kuò)展功能的方法即可沪编。
5.2.1 使用Decorator模式包裝request對象解決get請求中的中文參數(shù)亂碼問題
5.2.1.1 問題原因
Tomcat 7之前的版本,對于URL中字符的編碼都是使用iso8859-1
年扩。對于Get請求來說蚁廓,參數(shù)是放在URL中的,所以厨幻,對于GET請求相嵌,在獲得請求參數(shù)的時候,如果沒有進(jìn)行合適的轉(zhuǎn)碼操作况脆,取出的參數(shù)值就可能是亂碼饭宾。Tomcat 8以后默認(rèn)的URL編碼格式是utf-8。
在Tomcat配置文件conf/server.xml
中設(shè)置URIEncoding的值為UTF-8:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="utf-8"/>
但是不建議這么做格了。因為這樣相當(dāng)于應(yīng)用層的代碼依賴于Tomcat的設(shè)置看铆,有損可移植性。
這里用的是Tomcat 8笆搓,為了說明這個例子性湿,這里將Tomcat默認(rèn)的URL編碼方式改成了``
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="iso-8859-1"/>
5.2.1.2 代碼示例
首先,寫一個解決編碼問題的filter實現(xiàn)類满败,它的作用就是攔截請求肤频,然后,將請求做一個轉(zhuǎn)碼包裝算墨,然后放行宵荒。
com.lfqy.web.filter.CharacterEncodingFilter
:
package com.lfqy.web.filter;
import com.lfqy.web.wrapper.CharacterEncodingRequest;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by chengxia on 2019/11/13.
*/
public class CharacterEncodingFilter implements Filter {
private FilterConfig filterConfig = null;
//設(shè)置默認(rèn)的字符編碼
private String defaultCharset = "UTF-8";
public void init(FilterConfig filterConfig){
//在初始化時,得到過濾器的配置信息
this.filterConfig = filterConfig;
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//得到在web.xml中配置的字符編碼
String charset = filterConfig.getInitParameter("charset");
if(charset==null){
charset = defaultCharset;
}
request.setCharacterEncoding(charset);
response.setCharacterEncoding(charset);
response.setContentType("text/html;charset="+charset);
CharacterEncodingRequest requestWrapper = new CharacterEncodingRequest(request);
chain.doFilter(requestWrapper, response);
}
public void destroy(){
//do nothing in destory.
}
}
寫一個請求對象的包裝類,在包裝類中报咳,重寫獲取請求參數(shù)的getParameter方法侠讯,如果是get請求,就轉(zhuǎn)碼之后暑刃,再返回值厢漩。
com.lfqy.web.wrapper.CharacterEncodingRequest
:
package com.lfqy.web.wrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* Created by chengxia on 2019/11/11.
*/
public class CharacterEncodingRequest extends HttpServletRequestWrapper {
//定義一個成員變量,該對象就是被增強對象
private HttpServletRequest req;
//定義一個構(gòu)造函數(shù)岩臣,其參數(shù)是被增強對象
public CharacterEncodingRequest(HttpServletRequest req){
super(req);
this.req = req;
}
@Override
public String getParameter(String name){
try{
//獲取參數(shù)的值
String value= this.req.getParameter(name);
if(value==null){
return null;
}
//如果不是以get方式提交數(shù)據(jù)的溜嗜,就直接返回獲取到的值
if(!this.req.getMethod().equalsIgnoreCase("get")) {
return value;
}else{
//如果是以get方式提交數(shù)據(jù)的,就對獲取到的值進(jìn)行轉(zhuǎn)碼處理
value = new String(value.getBytes("ISO8859-1"),this.req.getCharacterEncoding());
return value;
}
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
接下來寫一個jsp頁面架谎,用來分別發(fā)送GET請求和POST請求:
EncodingFilterTest.jsp
:
<%--
Created by IntelliJ IDEA.
User: chengxia
Date: 2019/11/13
Time: 7:53 AM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入jstl標(biāo)簽庫 --%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Encoding Filter Test</title>
</head>
<body>
<%--使用c:url標(biāo)簽構(gòu)建url炸宵,構(gòu)建好的url存儲在reqGetUrl變量中--%>
<c:url value="/EncodingTestServlet" scope="page" var="reqGetUrl">
<%--構(gòu)建的url的附帶的中文參數(shù) ,參數(shù)名是:petname谷扣,值是:于泡泡--%>
<c:param name="petname" value="于泡泡"></c:param>
</c:url>
<%--使用get的方式訪問 --%>
<a href="${reqGetUrl}">超鏈接(get方式請求)</a>
<hr/>
<%--使用post方式提交表單 --%>
<form action="${pageContext.request.contextPath}/EncodingTestServlet" method="post">
用戶名:<input type="text" name="petname" value="于泡泡" />
<input type="submit" value="post方式提交">
</form>
</body>
</html>
為了接收前面的POST請求土全,需要再寫一個Servlet。
com.lfqy.web.servlet.EncodingTestServlet
:
package com.lfqy.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by chengxia on 2019/11/13.
*/
public class EncodingTestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//接收參數(shù)
String petname = request.getParameter("petname");
//獲取請求方式
String method = request.getMethod();
//獲取輸出流
PrintWriter out = response.getWriter();
out.write("請求的方式:"+method);
out.write("<br/>");
out.write("接收到的參數(shù):"+petname);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
最后看下配置文件WEB-INF/web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>FilterTrial01</filter-name>
<filter-class>com.lfqy.web.filter.FilterTrial01</filter-class>
</filter>
<filter>
<filter-name>FilterInitParamTrial</filter-name>
<filter-class>com.lfqy.web.filter.FilterInitParamTrial</filter-class>
<init-param>
<description>測試Filter配置參數(shù)01</description>
<param-name>FilterName</param-name>
<param-value>PaopaoFilter</param-value>
</init-param>
<init-param>
<description>測試Filter配置參數(shù)02</description>
<param-name>Function</param-name>
<param-value>Test filter init param...</param-value>
</init-param>
</filter>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.lfqy.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>設(shè)置編碼信息</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FilterTrial01</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>FilterInitParamTrial</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>EncodingTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.EncodingTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EncodingTestServlet</servlet-name>
<url-pattern>/EncodingTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.PostUrlParamTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<url-pattern>/PostUrlParamTestServlet</url-pattern>
</servlet-mapping>
</web-app>
啟動項目在Tomcat服務(wù)器上運行会涎,然后訪問http://localhost:8080/EncodingFilterTest.jsp
裹匙,效果如下:
這樣,無論點擊鏈接還是點擊按鈕在塔,都會能夠得到正確的請求參數(shù)并回顯幻件。
5.2.2 使用Decorator模式包裝request對象實現(xiàn)HTML字符的轉(zhuǎn)義
用戶在瀏覽器頁面輸入的內(nèi)容,如果其中含有HTML的中需要轉(zhuǎn)義的字符蛔溃,需要進(jìn)行轉(zhuǎn)義之后才能夠正常顯示绰沥。這里就介紹如何通過裝飾器實現(xiàn)該功能。
首先贺待,新建一個裝飾器類徽曲,用于實現(xiàn)請求內(nèi)容中參數(shù)值的轉(zhuǎn)義。
com.lfqy.web.wrapper.HTMLCharacterEscapeRequest
:
package com.lfqy.web.wrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* Created by chengxia on 2019/11/11.
*/
public class HTMLCharacterEscapeRequest extends HttpServletRequestWrapper {
//定義一個成員變量麸塞,該對象就是被增強對象
private HttpServletRequest req;
//定義一個構(gòu)造函數(shù)秃臣,其參數(shù)是被增強對象
public HTMLCharacterEscapeRequest(HttpServletRequest req){
super(req);
this.req = req;
}
@Override
public String getParameter(String name){
//獲取參數(shù)的值
String value= this.req.getParameter(name);
if(value==null || value.length() ==0 ){
return value;
}
return filter(value);
}
private String filter(String msg){
if (msg == null){
return null;
}
char content[] = new char[msg.length()];
msg.getChars(0, msg.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[I]);
}
}
return result.toString();
}
}
新建一個filter實現(xiàn)類。
com.lfqy.web.filter.HTMLCharacterEscapeFilter
:
package com.lfqy.web.filter;
import com.lfqy.web.wrapper.CharacterEncodingRequest;
import com.lfqy.web.wrapper.HTMLCharacterEscapeRequest;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by chengxia on 2019/11/13.
*/
public class HTMLCharacterEscapeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//do nothing
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
HTMLCharacterEscapeRequest requestWrapper = new HTMLCharacterEscapeRequest(request);
chain.doFilter(requestWrapper, response);
}
public void destroy(){
//do nothing in destory.
}
}
寫一個jsp頁面哪工,用來測試奥此。
HTMLCharacterEscapeTest.jsp
:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>Html Character Escape Test</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/HTMLCharacterEscapeTestServlet" method="post">
留言:
<textarea rows="8" cols="70" name="message">
<script type="text/javascript">
alert("This is my house.")
</script>
<a >An Unknown Website</a>
</textarea>
<input type="submit" value="發(fā)表">
</form>
</body>
</html>
寫一個Servlet,用于接收測試頁面發(fā)送的請求雁比。
com.lfqy.web.servlet.HTMLCharacterEscapeTestServlet
:
package com.lfqy.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by chengxia on 2019/11/13.
*/
public class HTMLCharacterEscapeTestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//接收參數(shù)
String msg = request.getParameter("message");
//獲取輸出流
PrintWriter out = response.getWriter();
out.write("message got:"+"<br/>"+msg);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
最后稚虎,在配置文件中,配置Servlet和過濾器偎捎。
WEB-INF/web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>FilterTrial01</filter-name>
<filter-class>com.lfqy.web.filter.FilterTrial01</filter-class>
</filter>
<filter>
<filter-name>FilterInitParamTrial</filter-name>
<filter-class>com.lfqy.web.filter.FilterInitParamTrial</filter-class>
<init-param>
<description>測試Filter配置參數(shù)01</description>
<param-name>FilterName</param-name>
<param-value>PaopaoFilter</param-value>
</init-param>
<init-param>
<description>測試Filter配置參數(shù)02</description>
<param-name>Function</param-name>
<param-value>Test filter init param...</param-value>
</init-param>
</filter>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.lfqy.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>設(shè)置編碼信息</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter>
<filter-name>HTMLCharacterEscapeFilter</filter-name>
<filter-class>com.lfqy.web.filter.HTMLCharacterEscapeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTrial01</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>FilterInitParamTrial</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>HTMLCharacterEscapeFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>EncodingTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.EncodingTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EncodingTestServlet</servlet-name>
<url-pattern>/EncodingTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.PostUrlParamTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<url-pattern>/PostUrlParamTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HTMLCharacterEscapeTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.HTMLCharacterEscapeTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HTMLCharacterEscapeTestServlet</servlet-name>
<url-pattern>/HTMLCharacterEscapeTestServlet</url-pattern>
</servlet-mapping>
</web-app>
啟動服務(wù)器之后蠢终,訪問http://localhost:8080/HTMLCharacterEscapeTest.jsp
序攘,效果如下:
點擊頁面上的
發(fā)表
,效果如下寻拂。可以看到程奠,前面的留言內(nèi)容中的字符都已經(jīng)被轉(zhuǎn)義了。
5.2.3 使用Decorator模式包裝request對象實現(xiàn)敏感字符過濾
首先祭钉,新建一個filter實現(xiàn)類瞄沙,在初始化方法中,讀取敏感詞列表慌核,加載到內(nèi)存帕识。同時,實現(xiàn)一個內(nèi)部類遂铡,包裝request類,重新實現(xiàn)獲取參數(shù)值的方法晶姊。
com.lfqy.web.filter.DirtyWordsFilter
:
package com.lfqy.web.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* Created by chengxia on 2019/11/13.
*/
public class DirtyWordsFilter implements Filter {
private FilterConfig config = null;
private List<String> dirtyWords;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
dirtyWords = getDirtyWords();
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
DirtyWordsRequest dirtyRequest = new DirtyWordsRequest(request);
chain.doFilter(dirtyRequest, response);
}
@Override
public void destroy() {
}
/**
* @Method: getDirtyWords
* @Description: 獲取敏感字符
* @Anthor:SpaceCatt
*
* @return
*/
private List<String> getDirtyWords(){
List<String> dirtyWords = new ArrayList<String>();
String dirtyWordPath = config.getInitParameter("DirtyWordsFilePath");
InputStream inputStream = config.getServletContext().getResourceAsStream(dirtyWordPath);
InputStreamReader is = null;
try {
is = new InputStreamReader(inputStream,"UTF-8");
} catch (UnsupportedEncodingException e2) {
e2.printStackTrace();
}
BufferedReader reader = new BufferedReader(is);
String line;
try {
while ((line = reader.readLine())!= null) {//如果 line為空說明讀完了
dirtyWords.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return dirtyWords;
}
/**
* @ClassName: DirtyWordsRequest
* @Description: 使用Decorator模式包裝request對象扒接,實現(xiàn)敏感字符過濾功能
* @author: spacecat
* @date: 2019-12-6 上午08:56:35
*
*/
class DirtyWordsRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
public DirtyWordsRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
/* 重寫getParameter方法,實現(xiàn)對敏感字符的過濾
* @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
*/
@Override
public String getParameter(String name) {
String value = this.request.getParameter(name);
if(value==null){
return null;
}
for(String dirtyWord : dirtyWords){
if(value.contains(dirtyWord)){
System.out.println("內(nèi)容中包含敏感詞:"+dirtyWord+"们衙,將會被替換成****");
//替換敏感字符
value = value.replace(dirtyWord, "****");
}
}
return value;
}
}
}
然后钾怔,寫一個測試頁面,提交帶敏感詞的表單內(nèi)容蒙挑。
DirtyWordsFilterTest.jsp
:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>Html Character Escape Test</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/HTMLCharacterEscapeTestServlet" method="post">
留言:
<textarea rows="8" cols="70" name="message">
這是我的留言宗侦,包含敏感詞1,敏感詞2等敏感詞忆蚀。哈哈
</textarea>
<input type="submit" value="發(fā)表">
</form>
</body>
</html>
這里表單的數(shù)據(jù)直接提交到com.lfqy.web.servlet.HTMLCharacterEscapeTestServlet
即可矾利,無需新寫。
最后修改配置文件馋袜。
WEB-INF/web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>FilterTrial01</filter-name>
<filter-class>com.lfqy.web.filter.FilterTrial01</filter-class>
</filter>
<filter>
<filter-name>FilterInitParamTrial</filter-name>
<filter-class>com.lfqy.web.filter.FilterInitParamTrial</filter-class>
<init-param>
<description>測試Filter配置參數(shù)01</description>
<param-name>FilterName</param-name>
<param-value>PaopaoFilter</param-value>
</init-param>
<init-param>
<description>測試Filter配置參數(shù)02</description>
<param-name>Function</param-name>
<param-value>Test filter init param...</param-value>
</init-param>
</filter>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.lfqy.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>設(shè)置編碼信息</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter>
<filter-name>DirtyWordsFilter</filter-name>
<filter-class>com.lfqy.web.filter.DirtyWordsFilter</filter-class>
<init-param>
<description>設(shè)置包含敏感詞的配置文件路徑</description>
<param-name>DirtyWordsFilePath</param-name>
<param-value>/WEB-INF/DirtyWords.txt</param-value>
</init-param>
</filter>
<filter>
<filter-name>HTMLCharacterEscapeFilter</filter-name>
<filter-class>com.lfqy.web.filter.HTMLCharacterEscapeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTrial01</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>FilterInitParamTrial</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>HTMLCharacterEscapeFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>DirtyWordsFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>EncodingTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.EncodingTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EncodingTestServlet</servlet-name>
<url-pattern>/EncodingTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.PostUrlParamTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<url-pattern>/PostUrlParamTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HTMLCharacterEscapeTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.HTMLCharacterEscapeTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HTMLCharacterEscapeTestServlet</servlet-name>
<url-pattern>/HTMLCharacterEscapeTestServlet</url-pattern>
</servlet-mapping>
</web-app>
啟動tomcat之后男旗,訪問http://localhost:8080/DirtyWordsFilterTest.jsp
,效果如下:
點擊
發(fā)表
欣鳖,可以看到關(guān)鍵詞已經(jīng)都被替換:在實際中察皇,我們經(jīng)常將上面的三個過濾器合并成一個。如下:
com.lfqy.web.filter.TripleInOneFilter
:
package com.lfqy.web.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* Created by chengxia on 2019/11/13.
*/
public class TripleInOneFilter implements Filter {
private FilterConfig config = null;
private List<String> dirtyWords;
//設(shè)置默認(rèn)的字符編碼
private String defaultCharset = "UTF-8";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
dirtyWords = getDirtyWords();
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//得到在web.xml中配置的字符編碼
String charset = config.getInitParameter("charset");
if(charset==null){
charset = defaultCharset;
}
request.setCharacterEncoding(charset);
response.setCharacterEncoding(charset);
response.setContentType("text/html;charset="+charset);
TripleInOneRequest filteredRequest = new TripleInOneRequest(request);
chain.doFilter(filteredRequest, response);
}
@Override
public void destroy() {
}
/**
* @Method: getDirtyWords
* @Description: 獲取敏感字符
* @Anthor:SpaceCat
*
* @return
*/
private List<String> getDirtyWords(){
List<String> dirtyWords = new ArrayList<String>();
String dirtyWordPath = config.getInitParameter("DirtyWordsFilePath");
InputStream inputStream = config.getServletContext().getResourceAsStream(dirtyWordPath);
InputStreamReader is = null;
try {
is = new InputStreamReader(inputStream,"UTF-8");
} catch (UnsupportedEncodingException e2) {
e2.printStackTrace();
}
BufferedReader reader = new BufferedReader(is);
String line;
try {
while ((line = reader.readLine())!= null) {//如果 line為空說明讀完了
dirtyWords.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return dirtyWords;
}
/**
* @ClassName: TripleInOneRequest
* @Description: 使用Decorator模式包裝request對象泽台,實現(xiàn)敏感字符過濾功能
* @author: spacecat
* @date: 2019-12-6 上午08:56:35
*
*/
class TripleInOneRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
public TripleInOneRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
/* 重寫getParameter方法什荣,實現(xiàn)對敏感字符的過濾
* @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
*/
@Override
public String getParameter(String name) {
//獲取參數(shù)的值
String value= this.request.getParameter(name);
if(value==null){
return null;
}
//如果不是以get方式提交數(shù)據(jù)的,就直接返回獲取到的值怀酷;如果是get方法稻爬,就需要進(jìn)行編碼轉(zhuǎn)換
if(!this.request.getMethod().equalsIgnoreCase("get")) {
return value;
}else{
try {
//如果是以get方式提交數(shù)據(jù)的,就對獲取到的值進(jìn)行轉(zhuǎn)碼處理
value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
}catch (Exception e){
e.printStackTrace();
}
}
//html字符轉(zhuǎn)義
value = filter(value);
//敏感詞過濾
for(String dirtyWord : dirtyWords){
if(value.contains(dirtyWord)){
System.out.println("內(nèi)容中包含敏感詞:"+dirtyWord+"胰坟,將會被替換成****");
//替換敏感字符
value = value.replace(dirtyWord, "****");
}
}
return value;
}
public String filter(String value) {
if (value == null){
return null;
}
char content[] = new char[value.length()];
value.getChars(0, value.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[I]);
}
}
return (result.toString());
}
}
}
在配置文件中添加的配置信息如下:
WEB-INF/web.xml
:
<filter>
<filter-name>DirtyWordsFilter</filter-name>
<filter-class>com.lfqy.web.filter.DirtyWordsFilter</filter-class>
<init-param>
<description>設(shè)置編碼信息</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<description>設(shè)置包含敏感詞的配置文件路徑</description>
<param-name>DirtyWordsFilePath</param-name>
<param-value>/WEB-INF/DirtyWords.txt</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>TripleInOneFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
5.2.4 使用Decorator設(shè)計模式包裝response對象實現(xiàn)壓縮響應(yīng)正文內(nèi)容
通過filter向目標(biāo)頁面?zhèn)鬟f一個自定義的response對象因篇。在自定義的response對象中泞辐,重寫getOutputStream方法和getWriter方法,使目標(biāo)資源調(diào)用此方法輸出頁面內(nèi)容時竞滓,獲得的是我們自定義的ServletOutputStream對象咐吼。在我們自定義的ServletOuputStream對象中,重寫write方法商佑,使寫出的數(shù)據(jù)寫出到一個buffer中(這里實際上是寫到了java.io.ByteArrayOutputStream
中锯茄,這個流自帶一個自動增長的buffer,所有到輸出到該流的數(shù)據(jù)都會先到buffer)茶没。當(dāng)頁面完成輸出后肌幽,通過調(diào)用自定義response對象的getBuffer()方法,在filter中就可得到頁面寫出的數(shù)據(jù)抓半,從而我們可以調(diào)用GzipOuputStream對數(shù)據(jù)進(jìn)行壓縮后再寫出給瀏覽器喂急,以此完成響應(yīng)正文件壓縮功能。
首先笛求,實現(xiàn)一個自定義的過濾器類廊移。
com.lfqy.web.filter.GzipFilter
:
package com.lfqy.web.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPOutputStream;
/**
* Created by chengxia on 2019/11/13.
*/
public class GzipFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
BufferedResponse bufResp = new BufferedResponse(response);
chain.doFilter(request, bufResp);
//拿出緩存中的數(shù)據(jù),壓縮后再打給瀏覽器
byte out[] = bufResp.getBuffer();
System.out.println("原始大小:" + out.length);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
//壓縮輸出流中的數(shù)據(jù)
GZIPOutputStream gout = new GZIPOutputStream(bout);
gout.write(out);
gout.close();
byte gzip[] = bout.toByteArray();
System.out.println("壓縮后的大小:" + gzip.length);
response.setHeader("content-encoding", "gzip");
response.setContentLength(gzip.length);
response.getOutputStream().write(gzip);
}
@Override
public void destroy() {
}
/**
* @ClassName: BufferedResponse
* @Description:
* 使用Decorator模式包裝response對象探入,輸出到帶緩存的ByteArrayOutputStream功能
* 同時狡孔,實現(xiàn)了getBuffer方法,使能夠拿到緩沖區(qū)的內(nèi)容
* @author: spacecat
* @date: 2019-12-6 上午08:56:35
*
*/
class BufferedResponse extends HttpServletResponseWrapper {
private ByteArrayOutputStream bout = new ByteArrayOutputStream();
private PrintWriter pw;
private HttpServletResponse response;
public BufferedResponse(HttpServletResponse response) {
super(response);
this.response = response;
}
/**
* 這個方法是我們壓縮之后蜂嗽,再向瀏覽器寫數(shù)據(jù)的時候苗膝,要調(diào)用的。
* */
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyServletOutputStream(bout);
}
/**
* 這個方法是框架輸出到response對象時調(diào)用的
* */
@Override
public PrintWriter getWriter() throws IOException {
pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));
return pw;
}
public byte[] getBuffer(){
try{
if(pw!=null){
pw.close();
}
if(bout!=null){
bout.flush();
return bout.toByteArray();
}
return null;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class MyServletOutputStream extends ServletOutputStream{
private ByteArrayOutputStream bout;
public MyServletOutputStream(ByteArrayOutputStream bout){
this.bout = bout;
}
@Override
public void write(int b) throws IOException {
this.bout.write(b);
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
}
}
修改配置文件植旧,說明那些需要壓縮辱揭。
WEB-INF/web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>FilterTrial01</filter-name>
<filter-class>com.lfqy.web.filter.FilterTrial01</filter-class>
</filter>
<filter>
<filter-name>FilterInitParamTrial</filter-name>
<filter-class>com.lfqy.web.filter.FilterInitParamTrial</filter-class>
<init-param>
<description>測試Filter配置參數(shù)01</description>
<param-name>FilterName</param-name>
<param-value>PaopaoFilter</param-value>
</init-param>
<init-param>
<description>測試Filter配置參數(shù)02</description>
<param-name>Function</param-name>
<param-value>Test filter init param...</param-value>
</init-param>
</filter>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.lfqy.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>設(shè)置編碼信息</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter>
<filter-name>DirtyWordsFilter</filter-name>
<filter-class>com.lfqy.web.filter.DirtyWordsFilter</filter-class>
<init-param>
<description>設(shè)置編碼信息</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<description>設(shè)置包含敏感詞的配置文件路徑</description>
<param-name>DirtyWordsFilePath</param-name>
<param-value>/WEB-INF/DirtyWords.txt</param-value>
</init-param>
</filter>
<filter>
<filter-name>TripleInOneFilter</filter-name>
<filter-class>com.lfqy.web.filter.TripleInOneFilter</filter-class>
<init-param>
<description>設(shè)置包含敏感詞的配置文件路徑</description>
<param-name>DirtyWordsFilePath</param-name>
<param-value>/WEB-INF/DirtyWords.txt</param-value>
</init-param>
</filter>
<filter>
<filter-name>GzipFilter</filter-name>
<filter-class>com.lfqy.web.filter.GzipFilter</filter-class>
</filter>
<filter>
<filter-name>HTMLCharacterEscapeFilter</filter-name>
<filter-class>com.lfqy.web.filter.HTMLCharacterEscapeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTrial01</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>FilterInitParamTrial</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>HTMLCharacterEscapeFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>DirtyWordsFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>TripleInOneFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--jsp文件的輸出的內(nèi)容都經(jīng)過壓縮過濾器壓縮后才輸出 -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
<!-- 配置過濾器的攔截方式-->
<!-- 對于在Servlet中通過
request.getRequestDispatcher("jsp頁面路徑").forward(request, response)
方式訪問的Jsp頁面的要進(jìn)行攔截 -->
<dispatcher>FORWARD</dispatcher>
<!--對于直接以URL方式訪問的jsp頁面進(jìn)行攔截,過濾器的攔截方式默認(rèn)就是 REQUEST-->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<!--js文件的輸出的內(nèi)容都經(jīng)過壓縮過濾器壓縮后才輸出 -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.js</url-pattern>
</filter-mapping>
<!--css文件的輸出的內(nèi)容都經(jīng)過壓縮過濾器壓縮后才輸出 -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.css</url-pattern>
</filter-mapping>
<!--html文件的輸出的內(nèi)容都經(jīng)過壓縮過濾器壓縮后才輸出 -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>EncodingTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.EncodingTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EncodingTestServlet</servlet-name>
<url-pattern>/EncodingTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.PostUrlParamTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<url-pattern>/PostUrlParamTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HTMLCharacterEscapeTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.HTMLCharacterEscapeTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HTMLCharacterEscapeTestServlet</servlet-name>
<url-pattern>/HTMLCharacterEscapeTestServlet</url-pattern>
</servlet-mapping>
</web-app>
這樣病附,啟動tomcat服務(wù)器之后界阁,訪問http://localhost:8080/DirtyWordsFilterTest.jsp
,頁面正常顯示胖喳,服務(wù)器控制臺輸出如下:
Before the request is handled...
url: http://localhost:8080/DirtyWordsFilterTest.jsp
原始大小:376
壓縮后的大小:300
After the request is handled...
5.2.5 使用Decorator設(shè)計模式包裝response對象實現(xiàn)緩存數(shù)據(jù)到內(nèi)存
對于頁面中很少更新的數(shù)據(jù)泡躯,例如商品分類,為避免每次都要從數(shù)據(jù)庫查詢分類數(shù)據(jù)丽焊,因此可把分類數(shù)據(jù)緩存在內(nèi)存或文件中较剃,以此來減輕數(shù)據(jù)庫或者磁盤的壓力,提高系統(tǒng)響應(yīng)速度技健。
原理上写穴,這里也是用自定義的Response對象將輸出先放到緩存,然后雌贱,緩存的數(shù)據(jù)放到一個映射結(jié)構(gòu)中啊送。這樣偿短,后續(xù)如果在內(nèi)存中命中,就不用重新查詢數(shù)據(jù)庫或者訪問磁盤了馋没。
首先寫一個自定義過濾器實現(xiàn)類昔逗。
com.lfqy.web.filter.WebResourceCachedFilter
:
package com.lfqy.web.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
/**
* Created by chengxia on 2019/11/13.
*/
public class WebResourceCachedFilter implements Filter {
//用一個map結(jié)構(gòu)緩存web資源
private Map<String,byte[]> map = new HashMap<String,byte[]>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//1.得到用戶請求的uri
String uri = request.getRequestURI();
//2.看緩存中有沒有uri對應(yīng)的數(shù)據(jù)
byte b[] = map.get(uri);
//3.如果緩存中有,直接拿緩存的數(shù)據(jù)打給瀏覽器篷朵,程序返回
if(b!=null){
//根據(jù)字節(jié)數(shù)組和指定的字符編碼構(gòu)建字符串
String webResourceHtmlStr = new String(b,response.getCharacterEncoding());
System.out.println(webResourceHtmlStr);
response.getOutputStream().write(b);
return;
}
//4.如果緩存沒有勾怒,讓目標(biāo)資源執(zhí)行,并捕獲目標(biāo)資源的輸出
BufferedResponse myresponse = new BufferedResponse(response);
chain.doFilter(request, myresponse);
//獲取緩沖流中的內(nèi)容的字節(jié)數(shù)組
byte out[] = myresponse.getBuffer();
//5.把資源的數(shù)據(jù)以用戶請求的uri為關(guān)鍵字保存到緩存中
map.put(uri, out);
//6.把數(shù)據(jù)打給瀏覽器
response.getOutputStream().write(out);
}
@Override
public void destroy() {
}
/**
* @ClassName: BufferedResponse
* @Description:
* 使用Decorator模式包裝response對象声旺,輸出到帶緩存的ByteArrayOutputStream功能
* 同時笔链,實現(xiàn)了getBuffer方法,使能夠拿到緩沖區(qū)的內(nèi)容
* @author: spacecat
* @date: 2019-12-6 上午08:56:35
*
*/
class BufferedResponse extends HttpServletResponseWrapper {
private ByteArrayOutputStream bout = new ByteArrayOutputStream();
private PrintWriter pw;
private HttpServletResponse response;
public BufferedResponse(HttpServletResponse response) {
super(response);
this.response = response;
}
/**
* 這個方法是我們壓縮之后腮猖,再向瀏覽器寫數(shù)據(jù)的時候鉴扫,要調(diào)用的。
* */
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyServletOutputStream(bout);
}
/**
* 這個方法是框架輸出到response對象時調(diào)用的
* */
@Override
public PrintWriter getWriter() throws IOException {
pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));
return pw;
}
public byte[] getBuffer(){
try{
if(pw!=null){
pw.close();
}
if(bout!=null){
bout.flush();
return bout.toByteArray();
}
return null;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class MyServletOutputStream extends ServletOutputStream{
private ByteArrayOutputStream bout;
public MyServletOutputStream(ByteArrayOutputStream bout){
this.bout = bout;
}
@Override
public void write(int b) throws IOException {
this.bout.write(b);
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
}
}
修改配置文件澈缺,指定緩存那些頁面幔妨。
WEB-INF/web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>FilterTrial01</filter-name>
<filter-class>com.lfqy.web.filter.FilterTrial01</filter-class>
</filter>
<filter>
<filter-name>FilterInitParamTrial</filter-name>
<filter-class>com.lfqy.web.filter.FilterInitParamTrial</filter-class>
<init-param>
<description>測試Filter配置參數(shù)01</description>
<param-name>FilterName</param-name>
<param-value>PaopaoFilter</param-value>
</init-param>
<init-param>
<description>測試Filter配置參數(shù)02</description>
<param-name>Function</param-name>
<param-value>Test filter init param...</param-value>
</init-param>
</filter>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.lfqy.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>設(shè)置編碼信息</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter>
<filter-name>DirtyWordsFilter</filter-name>
<filter-class>com.lfqy.web.filter.DirtyWordsFilter</filter-class>
<init-param>
<description>設(shè)置編碼信息</description>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<description>設(shè)置包含敏感詞的配置文件路徑</description>
<param-name>DirtyWordsFilePath</param-name>
<param-value>/WEB-INF/DirtyWords.txt</param-value>
</init-param>
</filter>
<filter>
<filter-name>TripleInOneFilter</filter-name>
<filter-class>com.lfqy.web.filter.TripleInOneFilter</filter-class>
<init-param>
<description>設(shè)置包含敏感詞的配置文件路徑</description>
<param-name>DirtyWordsFilePath</param-name>
<param-value>/WEB-INF/DirtyWords.txt</param-value>
</init-param>
</filter>
<filter>
<filter-name>GzipFilter</filter-name>
<filter-class>com.lfqy.web.filter.GzipFilter</filter-class>
</filter>
<filter>
<filter-name>WebResourceCachedFilter</filter-name>
<filter-class>com.lfqy.web.filter.WebResourceCachedFilter</filter-class>
</filter>
<filter>
<filter-name>HTMLCharacterEscapeFilter</filter-name>
<filter-class>com.lfqy.web.filter.HTMLCharacterEscapeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterTrial01</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>FilterInitParamTrial</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>HTMLCharacterEscapeFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>DirtyWordsFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>TripleInOneFilter</filter-name>
<!-- "/*"表示攔截所有的請求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--jsp文件的輸出的內(nèi)容都經(jīng)過壓縮過濾器壓縮后才輸出 -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
<!-- 配置過濾器的攔截方式-->
<!-- 對于在Servlet中通過
request.getRequestDispatcher("jsp頁面路徑").forward(request, response)
方式訪問的Jsp頁面的要進(jìn)行攔截 -->
<dispatcher>FORWARD</dispatcher>
<!--對于直接以URL方式訪問的jsp頁面進(jìn)行攔截,過濾器的攔截方式默認(rèn)就是 REQUEST-->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<!--js文件的輸出的內(nèi)容都經(jīng)過壓縮過濾器壓縮后才輸出 -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.js</url-pattern>
</filter-mapping>
<!--css文件的輸出的內(nèi)容都經(jīng)過壓縮過濾器壓縮后才輸出 -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.css</url-pattern>
</filter-mapping>
<!--html文件的輸出的內(nèi)容都經(jīng)過壓縮過濾器壓縮后才輸出 -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>WebResourceCachedFilter</filter-name>
<!-- 映射需要緩存輸出的JSP頁面谍椅,這幾個頁面都只是單純作為輸入UI,不會有太多的變化古话,因此可以緩存輸出 -->
<url-pattern>/DirtyWordsFilterTest.jsp</url-pattern>
<url-pattern>/test.jsp</url-pattern>
<url-pattern>/test2.jsp</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>EncodingTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.EncodingTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EncodingTestServlet</servlet-name>
<url-pattern>/EncodingTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.PostUrlParamTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PostUrlParamTestServlet</servlet-name>
<url-pattern>/PostUrlParamTestServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HTMLCharacterEscapeTestServlet</servlet-name>
<servlet-class>com.lfqy.web.servlet.HTMLCharacterEscapeTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HTMLCharacterEscapeTestServlet</servlet-name>
<url-pattern>/HTMLCharacterEscapeTestServlet</url-pattern>
</servlet-mapping>
</web-app>
啟動服務(wù)器之后雏吭,第二次訪問http://localhost:8080/DirtyWordsFilterTest.jsp
,服務(wù)器控制臺輸出如下:
Before the request is handled...
url: http://localhost:8080/DirtyWordsFilterTest.jsp
<!DOCTYPE HTML>
<html>
<head>
<title>Html Character Escape Test</title>
</head>
<body>
<form action="/HTMLCharacterEscapeTestServlet" method="post">
留言:
<textarea rows="8" cols="70" name="message">
這是我的留言陪踩,包含敏感詞1杖们,敏感詞2等敏感詞。哈哈
</textarea>
<input type="submit" value="發(fā)表">
</form>
</body>
</html>
原始大小:376
壓縮后的大小:300
After the request is handled...
注意肩狂,在最后的兩個例子中摘完,并沒有調(diào)用chain.doFilter(filteredRequest, response);
,也就是說傻谁,請求經(jīng)過這兩個filter處理之后孝治,就不會繼續(xù)往別的過濾器傳遞了。這里需要特別注意审磁。