日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

Head First JSP---随笔十(过滤器的威力)

發(fā)布時(shí)間:2025/3/15 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Head First JSP---随笔十(过滤器的威力) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

過(guò)濾器和包裝類

過(guò)濾器允許你攔截請(qǐng)求。最棒的是,servlet對(duì)此一無(wú)所知。


過(guò)濾器

3.3 描述Web容器請(qǐng)求處理模型;編寫和配置過(guò)濾器;創(chuàng)建請(qǐng)求或響應(yīng)包裝器;給定一個(gè)設(shè)計(jì)問(wèn)題,描述如何應(yīng)用過(guò)濾器或包裝器。
11.1 給定一個(gè)場(chǎng)景描述,列出了一系列問(wèn)題,選擇能夠解決這些問(wèn)題的模式。你必須了解的模式包括:
1. 攔截過(guò)濾器
2. 模型-視圖-控制器
3. 前端控制器
4. 服務(wù)定位器
5. 業(yè)務(wù)委托
6. 傳輸對(duì)象
11.1 對(duì)于以下設(shè)計(jì)模式,將各模式與使用該模式可能帶來(lái)的好處相匹配:
1. 攔截過(guò)濾器
2. 模型-視圖-控制器
3. 服務(wù)定位器
4. 業(yè)務(wù)委托
5. 傳輸對(duì)象


過(guò)濾器

能夠過(guò)濾一切東西!并且生命周期與servlet很類似。


過(guò)濾器是模塊化,在DD中配置

順序由DD來(lái)控制!


過(guò)濾器在3個(gè)方面很像servlet

  • 容器知道過(guò)濾器API。過(guò)濾器有自己的API。如果一個(gè)Java類實(shí)現(xiàn)了Filter接口,對(duì)容器來(lái)說(shuō)就有很大不同,這個(gè)類會(huì)從原先一個(gè)普通的Java類搖身一變而成為一個(gè)正式的J2EE過(guò)濾器。過(guò)濾器API的其他成員允許過(guò)濾器訪問(wèn)ServletContext,而且可以與其他過(guò)濾器鏈接。
  • 容器管理過(guò)濾器的生命周期。就像servlet一樣,過(guò)濾器也有一個(gè)生命周期。類似于servlet過(guò)濾器有init()和destroy()方法。對(duì)應(yīng)于servlet的doGet()/doPost()方法,過(guò)濾器則有一個(gè)doFilter()方法。
  • 都在DD中聲明。Web應(yīng)用可以有很多的過(guò)濾器,一個(gè)給定請(qǐng)求可能導(dǎo)致執(zhí)行多個(gè)過(guò)濾器。針對(duì)請(qǐng)求要運(yùn)行哪些過(guò)濾器,以及運(yùn)行的順序如何,這些都要在DD中聲明。

  • 建立請(qǐng)求跟蹤過(guò)濾器


    過(guò)濾器的生命周期

    每個(gè)過(guò)濾器都必須實(shí)現(xiàn)Filter接口中的三個(gè)方法:init()、doFilter()和destroy()。

  • 首先要有一個(gè)init()。容器決定實(shí)例化一個(gè)過(guò)濾器時(shí),就要把握住機(jī)會(huì),在init()方法中完成調(diào)用過(guò)濾器之前的所有初始化任務(wù)。前一頁(yè)顯示了最常見(jiàn)的實(shí)現(xiàn);也就是保存FilterConfig對(duì)象的一個(gè)引用,以備過(guò)濾器以后使用。
  • 真正的工作在doFilter()中完成。每次容器認(rèn)為應(yīng)該對(duì)當(dāng)前請(qǐng)求應(yīng)用過(guò)濾器時(shí),就會(huì)調(diào)用doFilter()方法。doFilter()方法有3個(gè)參數(shù):ServletRequest、ServletResponse、FilterChain,過(guò)濾器的功能要在doFilter()方法中實(shí)現(xiàn)。如果過(guò)濾器要把用戶記錄到一個(gè)文件中,就要在doFilter()中完成。你想壓縮響應(yīng)輸出嗎?也要在doFilter()中實(shí)現(xiàn)。
  • 最后是destroy()。容器決定刪除一個(gè)過(guò)濾器實(shí)例時(shí),會(huì)調(diào)用destroy()方法,這樣你就有機(jī)會(huì)在真正撤銷實(shí)例之前完成所需的所有清理工作。

  • 過(guò)濾器“入?!?/h3>

    多個(gè)過(guò)濾器同時(shí)工作!


    聲明和確定過(guò)濾器順序

    在DD中配置過(guò)濾器時(shí),通常會(huì)做3件事:

  • 聲明過(guò)濾器
  • 將過(guò)濾器映射到你想過(guò)濾的Web資源
  • 組織這些映射,創(chuàng)建過(guò)濾器調(diào)用序列
  • 如下(簡(jiǎn)單地說(shuō),就是可以過(guò)濾url和servlet,順序是先查找與之匹配的所有url再查找servlet將其按查找順序組成鏈):


    2.4版本中,過(guò)濾器可以應(yīng)用于請(qǐng)求分派器

    除了對(duì)url和servlet的過(guò)濾,還過(guò)濾轉(zhuǎn)發(fā)、包含、請(qǐng)求分派和錯(cuò)誤處理!


    用一個(gè)響應(yīng)端過(guò)濾器壓縮輸出

    在servlet完成其工作并從(虛擬)棧彈出后,過(guò)濾器還會(huì)得到機(jī)會(huì)執(zhí)行!

    不過(guò)事情沒(méi)有那么簡(jiǎn)單:

    那該如何解決這個(gè)問(wèn)題呢?往下看!


    可以實(shí)現(xiàn)自己的響應(yīng)

    容器已經(jīng)實(shí)現(xiàn)了HttpServletResponse接口:doFilter()和service()方法就是以這樣一個(gè)響應(yīng)作為參數(shù)。

    實(shí)現(xiàn)HttpServletResponse接口也太麻煩了吧,因?yàn)榉椒ê枚喟?#xff01;

    如何解決?下面!


    包裝器

    servlet API中的包裝器類功能極其強(qiáng)大,它們?yōu)槟阋b的東西實(shí)現(xiàn)了所需的所有方法,并將所有調(diào)用委托給底層的請(qǐng)求或響應(yīng)對(duì)象。如果想創(chuàng)建定制請(qǐng)求或響應(yīng)對(duì)象,只需派生某個(gè)便利請(qǐng)求或響應(yīng)“包裝器”類。包裝器包裝了實(shí)際請(qǐng)求或響應(yīng)對(duì)象,而且把調(diào)用委托給(傳給)實(shí)際的對(duì)象,還允許你對(duì)定制請(qǐng)求或響應(yīng)做所需的額外處理。

    4個(gè)“便利”類:

  • ServletRequestWrapper
  • HttpServletRequestWrapper
  • ServletResponseWrapper
  • HttpServletResponseWrapper
  • 這其實(shí)就是裝飾器模式。


    簡(jiǎn)單的包裝器例子


    包裝器第二版本


    具體的代碼

    過(guò)濾器代碼:

    package com.example.web;import java.io.IOException; import java.util.zip.GZIPOutputStream;import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;public class CompressioinFilter implements Filter{private ServletContext ctx;private FilterConfig cfg;/*** init方法保存配置對(duì)象,并保存* servlet上下文對(duì)象的一個(gè)直接* 引用*/@Overridepublic void init(FilterConfig cfg) throws ServletException {this.cfg = cfg;ctx = cfg.getServletContext();ctx.log(cfg.getFilterName()+" initialized.");}/*** 這個(gè)過(guò)濾器的核心是用裝飾器包裝響應(yīng)對(duì)象,它* 用一個(gè)壓縮I/O流包裝輸出流,當(dāng)且僅當(dāng)客戶包* 含一個(gè)Accept-Encoding首部(具體為gzip)時(shí),才會(huì)完成輸出流的壓縮。*/@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;String valid_encodings = request.getHeader("Accept-Encoding");if(valid_encodings.indexOf("gzip")>-1) {CompressioinResponseWrapper wrappedResp = new CompressioinResponseWrapper(response);wrappedResp.setHeader("Content-Encoding","gzip");//鏈接下一個(gè)組件fc.doFilter(request, wrappedResp);//GZIP壓縮流必須“結(jié)束”,這也會(huì)刷新輸出GZIP//流緩沖區(qū),將所有數(shù)據(jù)發(fā)送到原來(lái)的響應(yīng)流//容器處理余下的工作GZIPOutputStream gzos = wrappedResp.getGZIPOutputStream();gzos.flush();ctx.log(cfg.getFilterName() + ": finished the request.");}else {ctx.log(cfg.getFilterName() + ": no encoding performed.");fc.doFilter(request, response);}}//銷毀@Overridepublic void destroy() {cfg = null;ctx = null;}}

    包裝器代碼:

    package com.example.web;import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.zip.GZIPOutputStream;import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper;public class CompressioinResponseWrapper extends HttpServletResponseWrapper {//servlet響應(yīng)的壓縮輸出流private GZIPServletOutputStream servletGzipOS = null;//壓縮輸出流的PrintWriter對(duì)象private PrintWriter pw = null;CompressioinResponseWrapper(HttpServletResponse response) {//super構(gòu)造函數(shù)完成裝飾器的職責(zé)//保存所裝飾對(duì)象的一個(gè)引用,在這//里被裝飾的對(duì)象就是HTTP響應(yīng)對(duì)象super(response);}//忽略這個(gè)方法——輸出會(huì)得到壓縮@Overridepublic void setContentLength(int len) {}public GZIPOutputStream getGZIPOutputStream() {//過(guò)濾器使用這個(gè)裝飾器方法為壓縮過(guò)//濾器提供一個(gè)GZIP輸出流的句柄,以便//過(guò)濾器“完成”和刷新輸出GZIP流return this.servletGzipOS.internalGzipOS;}private Object streamUsed = null;//允許訪問(wèn)所裝飾的servlet輸出流@Overridepublic ServletOutputStream getOutputStream() throws IOException {if(streamUsed!=null&&streamUsed!=pw) {//僅當(dāng)servlet還沒(méi)有訪問(wèn)打印書(shū)寫器時(shí)//允許servlet訪問(wèn)servlet輸出流throw new IllegalStateException();}if(servletGzipOS==null) {//用我們的壓縮輸出流包裝原來(lái)的servlet輸出流servletGzipOS = new GZIPServletOutputStream(getResponse().getOutputStream());streamUsed = servletGzipOS;}return servletGzipOS;}@Overridepublic PrintWriter getWriter() throws IOException {if(streamUsed!=null&&streamUsed!=servletGzipOS) {//當(dāng)且僅當(dāng)servlet還沒(méi)有訪問(wèn)servlet輸出//流時(shí),允許servlet訪問(wèn)打印書(shū)寫器throw new IllegalStateException();}if(pw==null) {/*** 要建立一個(gè)打印書(shū)寫器,必須首先包裝servlet輸出流* 然后把壓縮servlet輸出流包裝在另外兩個(gè)輸出流裝飾器* 中:首先OutputStreamWrite把字符轉(zhuǎn)換為字節(jié),再用* PrintWriter包裝OutputStreamWriter對(duì)象。*/servletGzipOS = new GZIPServletOutputStream(getResponse().getOutputStream());OutputStreamWriter osw = new OutputStreamWriter(servletGzipOS, getResponse().getCharacterEncoding());pw = new PrintWriter(osw);streamUsed = pw;}return pw;} }

    輔助類:

    package com.example.web;import java.io.IOException; import java.util.zip.GZIPOutputStream;import javax.servlet.ServletOutputStream; import javax.servlet.WriteListener;public class GZIPServletOutputStream extends ServletOutputStream{//保存原始GZIP流的一個(gè)引用GZIPOutputStream internalGzipOS;@Overridepublic boolean isReady() {return false;}@Overridepublic void setWriteListener(WriteListener arg0) {}//裝飾器構(gòu)造函數(shù)GZIPServletOutputStream(ServletOutputStream sos) throws IOException {this.internalGzipOS = new GZIPOutputStream(sos);}@Overridepublic void write(int param) throws IOException {//這個(gè)方法把write()調(diào)用委托給GZIP壓縮流,//從而實(shí)現(xiàn)壓縮裝飾,GZIP壓縮流包裝了原來(lái)的//ServletOutputStreaminternalGzipOS.write(param);}}

    本章完。

    總結(jié)

    以上是生活随笔為你收集整理的Head First JSP---随笔十(过滤器的威力)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。