<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,否則將會報錯:
    嚴(yán)重: 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 閱讀(8171) 評論(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)

    個人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲日本一区二区三区| 国产一区视频在线免费观看 | 亚洲国产成人久久综合野外| 亚洲无线一二三四区手机| 亚洲乱码无码永久不卡在线| 亚洲综合无码一区二区三区| 亚洲va中文字幕| 手机看片国产免费永久| 麻豆国产精品免费视频| 四虎永久在线精品视频免费观看| 亚洲私人无码综合久久网| 韩国免费a级作爱片无码| 成年人网站在线免费观看| 狠狠色婷婷狠狠狠亚洲综合| 亚洲精品午夜视频| 100000免费啪啪18免进| MM131亚洲国产美女久久| 一级毛片视频免费| 国产在线观看麻豆91精品免费| 亚洲一卡2卡4卡5卡6卡在线99| 国产免费无码AV片在线观看不卡| 在线精品免费视频| 亚洲国产精品专区| 国色精品va在线观看免费视频| 亚洲AV无码乱码在线观看| 一级毛片免费一级直接观看| 国产亚洲精AA在线观看SEE | 三年片在线观看免费大全| 国产成人亚洲精品青草天美| 午夜亚洲国产精品福利| 在线观看的免费网站无遮挡| 亚洲欧洲∨国产一区二区三区| 一级做a爰片久久毛片免费陪| 国产成人免费ā片在线观看| 香蕉大伊亚洲人在线观看| 18勿入网站免费永久| 美女一级毛片免费观看| 亚洲av午夜成人片精品电影| 永久在线观看免费视频 | 精品国产麻豆免费人成网站| 亚洲一区二区三区免费在线观看|