1:過(guò)濾器概念
過(guò)濾器就是一種在請(qǐng)求目標(biāo)資源的中間組件,比喻把污水轉(zhuǎn)換成純凈水中間需要一個(gè)污水凈化設(shè)備,那么這個(gè)設(shè)備就好比一個(gè)過(guò)濾器。那么我用圖來(lái)表示過(guò)濾器(可以有多個(gè)過(guò)濾器)運(yùn)行的過(guò)程
2:Filter(過(guò)濾器)接口
Filter接口包含三個(gè)方法分別是init、doFilter、 destroy下面先逐個(gè)介紹。
2.1:public void init(FilterConfig filterConfig)
這個(gè)方法主要來(lái)完成初始化過(guò)濾器,容器調(diào)用這個(gè)方法的時(shí)候,向過(guò)濾器傳遞FilterConfig對(duì)象,F(xiàn)ilterConfig的用法和ServletConfig相似,利用FilterConfig對(duì)象可以得到ServletContext對(duì)象,以及可以得到部署描述符中過(guò)濾器初始化的參數(shù)。
2.2:public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
該方法和Servlet中的service相似,當(dāng)客戶(hù)端請(qǐng)求目標(biāo)資源的時(shí)候,容器就會(huì)調(diào)用與這個(gè)目標(biāo)資源相關(guān)聯(lián)的過(guò)濾器的doFilter方法,在這個(gè)方法中可以對(duì)請(qǐng)求和響應(yīng)進(jìn)行處理,實(shí)現(xiàn)過(guò)濾器的特定功能,在處理完成之后調(diào)用chain.doFilter把請(qǐng)求傳給下一個(gè)過(guò)濾器(目標(biāo)資源)
2.3:public void destroy()
當(dāng)過(guò)濾器生命結(jié)束的時(shí)候,容器就會(huì)調(diào)用該方法來(lái)釋放過(guò)濾器的資源
3:過(guò)濾器的配置
過(guò)濾器是通過(guò)<filter>和<filter-mapping>元素來(lái)完成的。
3.1:<filter>元素
<filter>元素的屬性,<filter-name>來(lái)為過(guò)濾器指定一個(gè)名字,<filter-class>元素用于指定過(guò)濾器完整的限定類(lèi)名,<init-param>用來(lái)為過(guò)濾器指定初始化參數(shù),他下面有2個(gè)屬性,一個(gè)是<param-name>參數(shù)名稱(chēng),另一個(gè)是<param-value>參數(shù)值。
3.2:<filter-mapping>元素
<filter-mapping>下面有3個(gè)主要的屬性,<filter-name>用來(lái)指定過(guò)濾已經(jīng)在容器聲明的過(guò)濾器名稱(chēng),<url-pattren>和<servlet-name>這兩個(gè)任選其中一個(gè),<url-pattren>表示當(dāng)請(qǐng)求這樣的url時(shí)候過(guò)濾器被調(diào)用,<servlet-name>表示當(dāng)這個(gè)Servlet被調(diào)用時(shí)候過(guò)濾器被調(diào)用(可以有多個(gè)Servlet)。
基本知識(shí)準(zhǔn)備完畢了,現(xiàn)在我們一起開(kāi)始進(jìn)行實(shí)踐。
4:過(guò)濾器時(shí)間應(yīng)用
4.1:過(guò)濾器解決中文亂碼問(wèn)題
由于Web容器默認(rèn)的編碼方式是ISO-8859-1,在Servlet/Jsp程序中,通過(guò)請(qǐng)求的對(duì)象的getParameter()方法得到的字符串是以ISO-8859-1轉(zhuǎn)換而來(lái)(有人說(shuō)我在jsp程序已經(jīng)設(shè)置了UTF-8為什么還出現(xiàn)這種情況呢,那是由于web容器再次對(duì)請(qǐng)求的數(shù)據(jù)進(jìn)行一次轉(zhuǎn)換,所以后來(lái)得到字符串就是ISO-8859-1編碼的),這就是導(dǎo)致亂碼的原因。如下圖
那么找到根源以后問(wèn)題就比較好解決了,核心代碼如下
public class EncodingFilter implements Filter {
protected String encoding=null;
class myRequestWrapper extends HttpServletRequestWrapper{
public myRequestWrapper(HttpServletRequest request) {
super(request);
}
public String getParameter(String param)
{
String value=null;
try{
//post提交
super.setCharacterEncoding(encoding);
value=super.getParameter(param);
if(super.getMethod().equalsIgnoreCase("GET"))//get提交
{
if(value!=null)
{
value=new String(value.getBytes("iso8859-1"), encoding);
}
}
}
catch(UnsupportedEncodingException e){
e.printStackTrace();
}
return value;
}
}
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding=filterConfig.getInitParameter("encoding");//從web容器來(lái)獲取過(guò)濾器初始化參數(shù)
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//避免響應(yīng)出現(xiàn)亂碼情況
response.setCharacterEncoding("text/html;charset="+this.encoding);
//把過(guò)濾器給下一個(gè)過(guò)濾器或者資源處理器
chain.doFilter(new myRequestWrapper((HttpServletRequest)request), response);
}
public void destroy() {
this.encoding=null;
}
}
對(duì)過(guò)濾器進(jìn)行配置
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.lp.filters.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<servlet-name>LoginServlet</servlet-name>
<!-- <url-pattern>/LoginServlet</url-pattern> -->
</filter-mapping>
5:過(guò)濾器使用場(chǎng)景
5.1:對(duì)用戶(hù)進(jìn)行統(tǒng)一驗(yàn)證
5.2:對(duì)用戶(hù)的訪(fǎng)問(wèn)要求進(jìn)行記錄或者審核
5.3:對(duì)用戶(hù)請(qǐng)求發(fā)送的數(shù)據(jù)進(jìn)行過(guò)濾或替換
5.4:轉(zhuǎn)換圖像格式
5.5:對(duì)響應(yīng)的內(nèi)容進(jìn)行壓縮,減少傳輸量
5.6:對(duì)請(qǐng)求和響應(yīng)進(jìn)行加解密處理
5.7:觸發(fā)資源訪(fǎng)問(wèn)事件