<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    聶永的博客

    記錄工作/學(xué)習(xí)的點點滴滴。

    Servlet 3.0筆記之異步攔截器(async filter)的學(xué)習(xí)

    異步Servlet有時需要一個攔截器,但必須是異步的Filter,否則將會報錯:
    嚴重: Servlet.service() for servlet [com.learn.servlet3.async.DemoAsyncLinkServlet] in context with path [/servlet3] threw exceptionjava.lang.IllegalStateException: Not supported.
    因此異步的Filter攔截異步Servlet,不要搞錯。
    我們需要預(yù)先定義這么一個異步連接,每秒輸出一個數(shù)字字符串,從0到99,諸如下面HTML字符串:
    <div>2</div>
    最后輸出Done!
    給出兩個訪問地址,一個用于被攔截(/demoAsyncLink),一個用于單獨訪問(/demoAsyncLink2),便于對照:
    /**
    * 模擬長連接實現(xiàn),每秒輸出一些信息
    *
    * @author yongboy
    * @date 2011-1-14
    * @version 1.0
    */
    @WebServlet(
    urlPatterns = { "/demoAsyncLink", "/demoAsyncLink2" },
    asyncSupported = true
    )
    public class DemoAsyncLinkServlet extends HttpServlet {
    private static final long serialVersionUID = 4617227991063927036L;

    protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
    response.setHeader("Cache-Control", "private");
    response.setHeader("Pragma", "no-cache");
    response.setHeader("Connection", "Keep-Alive");
    response.setHeader("Proxy-Connection", "Keep-Alive");
    response.setContentType("text/html;charset=UTF-8");

    PrintWriter out = response.getWriter();
    out.println("<div>Start ...</div>");
    out.flush();

    AsyncContext asyncContext = request.startAsync(request, response);

    new CounterThread(asyncContext).start();
    }

    private static class CounterThread extends Thread {
    private AsyncContext asyncContext;
    public CounterThread(AsyncContext asyncContext) {
    this.asyncContext = asyncContext;
    }

    @Override
    public void run() {
    int num = 0;
    int max = 100;
    int interval = 1000;

    // 必須設(shè)置過期時間,否則將會出連接過期,線程無法運行完畢異常
    asyncContext.setTimeout((max + 1) * interval);
    PrintWriter out = null;

    try {
    try {
    out = asyncContext.getResponse().getWriter();
    } catch (IOException e) {
    e.printStackTrace();
    }

    while (true) {
    out.println("<div>" + (num++) + "</div>");
    out.flush();

    if (num >= max) {
    break;
    }

    Thread.sleep(interval);
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }

    if (out != null) {
    out.println("<div>Done !</div>");
    out.flush();
    out.close();
    }

    asyncContext.complete();
    }
    }
    }
    若想讓HttpServletResponse包裝器發(fā)揮包裝的效果,須調(diào)用帶有參數(shù)的startAsync(request, response)方法開啟異步輸出,否則MarkWapperedResponse將不起作用。因為,若不傳遞現(xiàn)有的request,response對象,將會調(diào)用原生的request和response對象。
    在tomcat7下面,異步連接超時時間為10000單位,若不指定超時時間,遞增的數(shù)字不會按照預(yù)想完整輸出到99。
    我們假設(shè)需要定義這樣一個Filter,為每一次的異步輸出的內(nèi)容增加一個特殊標(biāo)記:
    <!--marked filter-->
    <div>2</div>
    邏輯很簡單,作為示范也不需要多復(fù)雜。
    再看看一個異步Filter的代碼:
    /**
    * 異步攔截器
    *
    * @author yongboy
    * @date 2011-1-14
    * @version 1.0
    */
    @WebFilter(
    dispatcherTypes = {
    DispatcherType.REQUEST,
    DispatcherType.FORWARD,
    DispatcherType.INCLUDE
    },
    urlPatterns = { "/demoAsyncLink" },
    asyncSupported = true //支持異步Servlet
    )
    public class AsyncServletFilter implements Filter {
    private Log log = LogFactory.getLog(AsyncServletFilter.class);

    public AsyncServletFilter() {
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {

    log.info("it was filted now");

    MarkWapperedResponse wapper = new MarkWapperedResponse(
    (HttpServletResponse) response);

    chain.doFilter(request, wapper);
    }

    public void init(FilterConfig fConfig) throws ServletException {
    }
    }
    很簡單,添加上asyncSupported = true屬性即可。在上面Filter中包裝了一個HttpServletResponse對象,目的在于返回一個定制的PrintWriter對象,簡單重寫flush方法(不見得方法多好):
    /**
    * HttpServletResponse簡單包裝器,邏輯簡單
    *
    * @author yongboy
    * @date 2011-1-14
    * @version 1.0
    */
    public class MarkWapperedResponse extends HttpServletResponseWrapper {
    private PrintWriter writer = null;
    private static final String MARKED_STRING = "<!--marked filter--->";

    public MarkWapperedResponse(HttpServletResponse resp) throws IOException {
    super(resp);

    writer = new MarkPrintWriter(super.getOutputStream());
    }

    @Override
    public PrintWriter getWriter() throws UnsupportedEncodingException {
    return writer;
    }

    private static class MarkPrintWriter extends PrintWriter{

    public MarkPrintWriter(OutputStream out) {
    super(out);
    }

    @Override
    public void flush() {
    super.flush();

    super.println(MARKED_STRING);
    }
    }
    }
    在瀏覽器端請求被包裝的/demoAsyncLink鏈接,截圖以及firebug檢測截圖如下:
     
    可以在瀏覽器內(nèi)同時請求/demoAsyncLink2前后作為對比一下。

    posted on 2011-01-15 19:39 nieyong 閱讀(8157) 評論(0)  編輯  收藏 所屬分類: Servlet3

    公告

    所有文章皆為原創(chuàng),若轉(zhuǎn)載請標(biāo)明出處,謝謝~

    新浪微博,歡迎關(guān)注:

    導(dǎo)航

    <2011年1月>
    2627282930311
    2345678
    9101112131415
    16171819202122
    23242526272829
    303112345

    統(tǒng)計

    常用鏈接

    留言簿(58)

    隨筆分類(130)

    隨筆檔案(151)

    個人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产成人精品日本亚洲网站| 自拍日韩亚洲一区在线| 成年黄网站色大免费全看| 精品亚洲AV无码一区二区三区 | 亚洲人成网站在线在线观看 | 456亚洲人成在线播放网站| 亚洲A∨午夜成人片精品网站| a毛片免费全部在线播放**| 国产成人亚洲综合一区| 亚洲一区二区三区在线播放| 国产h肉在线视频免费观看| 日韩少妇内射免费播放| 亚洲性色成人av天堂| 亚洲人成网站观看在线播放| 国产91免费在线观看| 亚洲免费在线观看| 亚洲高清有码中文字| 亚洲国产成人高清在线观看| 日本午夜免费福利视频| 中文字幕免费视频一| 一级毛片人与动免费观看| 色婷五月综激情亚洲综合| 亚洲AV综合色区无码一区爱AV | 亚洲免费闲人蜜桃| 乱淫片免费影院观看| 亚洲国产激情在线一区| 亚洲AV无码成人专区片在线观看 | 亚洲狠狠爱综合影院婷婷| www.999精品视频观看免费| 久久久久免费精品国产| 精品久久久久亚洲| 亚洲a视频在线观看| 亚洲精品在线观看视频| 中文字幕久久亚洲一区 | 成人免费毛片观看| 69视频免费在线观看| 最近的2019免费中文字幕| 美女隐私免费视频看| 亚洲熟女精品中文字幕| 亚洲高清在线播放| 夜夜春亚洲嫩草影院|