過濾器
概述
在請求與響應(yīng)數(shù)據(jù)之間,添加過濾
過濾器就是一個(gè)接口
javax.servlet.Filter
作用
過濾器是一個(gè)對象结缚,可以在請求資源時(shí),或者在響應(yīng)資源時(shí),或者在請求和響應(yīng)資源時(shí)秸架,執(zhí)行過濾任務(wù)础爬。
工作原理
瀏覽器發(fā)起的所有請求被過濾器攔截
過濾有效的請求給控制器
控制器響應(yīng)數(shù)據(jù)被過濾器攔截
返回瀏覽器
生命周期
實(shí)例化
初始化
執(zhí)行過濾
銷毀
init(FilterConfig)
初始化方法叠赦,在創(chuàng)建過濾器對象后調(diào)用
doFilter(request,response,FilterChain)
每次訪問目標(biāo)資源時(shí)都被調(diào)用
destory()
過濾器對象銷毀時(shí)調(diào)用
web應(yīng)用重新加載或web服務(wù)器停止了
應(yīng)用場合
對請求和響應(yīng)進(jìn)行統(tǒng)一處理
對請求進(jìn)行日志記錄和審核
對數(shù)據(jù)進(jìn)行屏蔽和替換
對數(shù)據(jù)進(jìn)行加密和解密
參數(shù)進(jìn)行中文編碼處理
登錄權(quán)限問題
API
Filter接口
Filter接口沒有實(shí)現(xiàn)類,編寫過濾器必須要實(shí)現(xiàn)該接口
常用方法
void init(FilterConfig filterConfig)
Web容器調(diào)用該方法實(shí)現(xiàn)過濾器的初始化
void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
客戶端請求資源時(shí)卷拘,Web容器會調(diào)用與資源對應(yīng)的過濾器的doFilter()方法。在該方法中祝高,可以對請求和響應(yīng)進(jìn)行處理栗弟,實(shí)現(xiàn)過濾器的功能
void destory()
Web容器調(diào)用該方法,造成過濾器失效
開發(fā)步驟
1.定義一個(gè)類OneFilter實(shí)現(xiàn)javax.servlet.Filter
2.實(shí)現(xiàn)doFilter方法
chain.doFilter(request,response);//是放行
3.web.xml配置
<filter>
<filter-name></filter-name>
<filter-class></filter-class>
</filter>
<filter-mapping>
<filter-name></filter-name>
<url-pattern></url-pattern>
</filter-mapping>
過濾器鏈
多個(gè)過濾器組成過濾器鏈
根據(jù)過濾器的配置工闺,按照先后順序執(zhí)行
按照filter-mapping配置的順序來執(zhí)行
初始化參數(shù)設(shè)置
<filter>
<filter-name>onefilter</filter-name>
<filter-class>com.shuai.filters.OneFilter</filter-class>
<init-param>
<param-name>user</param-name>
<param-value>shuaige</param-value>
</init-param>
</filter>
@Override
public void init(FilterConfig arg0) throws ServletException {
String user = arg0.getInitParameter("user");
}
過濾器映射配置
url-pattern 目標(biāo)資源訪問
精確過濾 /hello /hello
/itcast/hello /itcast/hello
模糊過濾 /* /任意路徑
/itcast/ /itcast/任意路徑
*.后綴 任意路徑.后綴
過濾內(nèi)容
一個(gè)過濾器可以同時(shí)過濾多個(gè)資源(靜態(tài)或者動態(tài)的)
如果資源是動態(tài)的servlet乍赫,可以使用名稱進(jìn)行過濾
過濾類型
<dispatcher>類型值</dispatcher>
過濾類型:在什么樣的請求下,過濾器才會生效陆蟆!
REQUEST:直接通過發(fā)出的請求 (默認(rèn))
FORWARD:通過轉(zhuǎn)發(fā)過來的請求
INCLUDE:通過包含方式過來的請求
ERROR:通過錯(cuò)誤頁面的方法過來的請求
什么是過濾器鏈
當(dāng)一個(gè)資源同時(shí)被多個(gè)過濾器所過濾雷厂,則形成一個(gè)過濾器鏈
注意:filter-mapping配置的順序決定了過濾器鏈中過濾調(diào)用的順序:先配置先被調(diào)用
案例
編碼過濾器
public class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String name) {
try {
String value = request.getParameter(name);
if("get".equalsIgnoreCase(request.getMethod())){
value = new String(value.getBytes("iso-8859-1"),"utf-8");
}
return value;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public String[] getParameterValues(String name) {
try {
String[] values = request.getParameterValues(name);
if("get".equalsIgnoreCase(request.getMethod())){
for(int i = 0;i<values.length;i++){
values[i] = new String(values[i].getBytes("iso-8859-1"),"utf-8");
}
}
return values;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public Map getParameterMap() {
try {
Map<String,String[]> map = request.getParameterMap();
if("get".equalsIgnoreCase(request.getMethod())){
for(Entry<String,String[]> entry:map.entrySet()){
String[] values = entry.getValue();
for(int i=0;i<values.length;i++){
values[i] = new String(values[i].getBytes("iso-8859-1"),"utf-8");
}
}
}
return map;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public class EncodeFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
MyRequest myRequest = new MyRequest((HttpServletRequest)request);
chain.doFilter(myRequest, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
頁面壓縮過濾器
public class MyResponse extends HttpServletResponseWrapper {
private HttpServletResponse response;
private CharArrayWriter buffer = new CharArrayWriter();
public MyResponse(HttpServletResponse response) {
super(response);
this.response = response;
}
public char[] getBuffer(){
return buffer.toCharArray();
}
@Override
public PrintWriter getWriter() throws IOException {
//返回一個(gè)帶CharArrayWriter緩存的PrintWriter對象
return new PrintWriter(buffer);
}
}
public class ContentGZIPFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
MyResponse myResponse = new MyResponse((HttpServletResponse)response);
//放行
chain.doFilter(request, myResponse);
//得到壓縮前的內(nèi)容
char[] content = myResponse.getBuffer();
System.out.println(new String(content).getBytes().length);
// 對網(wǎng)頁內(nèi)容進(jìn)行壓縮
// 1)創(chuàng)建臨時(shí)緩存區(qū)用于存放壓縮后的內(nèi)容
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// 2)創(chuàng)建GZIPOutputStream對象
GZIPOutputStream gzip = new GZIPOutputStream(bos);
// 3)開始壓縮(內(nèi)容壓縮到緩存區(qū)中)
gzip.write(new String(content).getBytes("UTF-8"));
// 壓縮結(jié)束
gzip.finish();
// 4)從緩存區(qū)取出壓縮后的內(nèi)容
byte[] result = bos.toByteArray();
System.out.println("壓縮后:" + result.length);
// 通知瀏覽器數(shù)據(jù)壓縮格式
myResponse.setHeader("content-encoding", "gzip");
// 把壓縮后的內(nèi)容寫出到瀏覽器
response.getOutputStream().write(result);
}
public void init(FilterConfig filterConfig) throws ServletException {}
public void destroy() {}
}
登錄過濾器
裝飾者模式
裝飾者使用場景
一個(gè)類的方法不能滿足開發(fā)者的需求,這時(shí)就可以使用裝飾者模式叠殷,對該類進(jìn)行裝飾改鲫,對其方法進(jìn)行(增強(qiáng))。
讓BufferedReader的readLine方法自動帶上一個(gè)編號(增強(qiáng)方法)林束,這時(shí)可以裝飾BufferedReader
裝飾步驟:
編寫一個(gè)裝飾類像棘,繼承被裝飾類(BufferedReader)(非final的)
聲明一個(gè)被裝飾類的成員變量
在裝飾類的構(gòu)造方法中,接收被裝飾類的實(shí)例
增強(qiáng)被裝飾類的方法
代理模式 vs 裝飾者模式
代理模式:著重于得到被代理類的方法的控制權(quán)
裝飾者模式:著重于增強(qiáng)被裝飾類的方法內(nèi)容
案例
服務(wù)器編碼過濾器
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者