servlet3.0的学习(二)

Servlet 3.0 异步传输的使用 

AjaxCometServlet.java 
Java代码   收藏代码
  1. import java.io.IOException;  
  2. import java.io.PrintWriter;  
  3. import java.util.Queue;  
  4. import java.util.concurrent.ConcurrentLinkedQueue;  
  5. import java.util.concurrent.BlockingQueue;  
  6. import java.util.concurrent.LinkedBlockingQueue;  
  7.   
  8. import javax.servlet.AsyncContext;  
  9. import javax.servlet.AsyncEvent;  
  10. import javax.servlet.AsyncListener;  
  11. import javax.servlet.ServletConfig;  
  12. import javax.servlet.ServletException;  
  13. import javax.servlet.annotation.WebServlet;  
  14. import javax.servlet.http.HttpServlet;  
  15. import javax.servlet.http.HttpServletRequest;  
  16. import javax.servlet.http.HttpServletResponse;  
  17.   
  18. @WebServlet(urlPatterns = {"/chat"}, asyncSupported = true)  
  19. public class AjaxCometServlet extends HttpServlet {  
  20.   
  21.     private static final Queue<AsyncContext> queue = new ConcurrentLinkedQueue<AsyncContext>();  
  22.   
  23.     private static final BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();  
  24.   
  25.     private static final String BEGIN_SCRIPT_TAG = "<script type='text/javascript'>\n";  
  26.   
  27.     private static final String END_SCRIPT_TAG = "</script>\n";  
  28.   
  29.     private static final long serialVersionUID = -2919167206889576860L;  
  30.   
  31.     private Thread notifierThread = null;  
  32.   
  33.     @Override  
  34.     public void init(ServletConfig config) throws ServletException {  
  35.         Runnable notifierRunnable = new Runnable() {  
  36.             public void run() {  
  37.                 boolean done = false;  
  38.                 while (!done) {  
  39.                     String cMessage = null;  
  40.                     try {  
  41.                         cMessage = messageQueue.take();  
  42.                         for (AsyncContext ac : queue) {  
  43.                             try {  
  44.                                 PrintWriter acWriter = ac.getResponse().getWriter();  
  45.                                 acWriter.println(cMessage);  
  46.                                 acWriter.flush();  
  47.                             } catch(IOException ex) {  
  48.                                 System.out.println(ex);  
  49.                                 queue.remove(ac);  
  50.                             }  
  51.                         }  
  52.                     } catch(InterruptedException iex) {  
  53.                         done = true;  
  54.                         System.out.println(iex);  
  55.                     }  
  56.                 }  
  57.             }  
  58.         };  
  59.         notifierThread = new Thread(notifierRunnable);  
  60.         notifierThread.start();  
  61.     }  
  62.   
  63.     @Override  
  64.     protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {  
  65.         res.setContentType("text/html");  
  66.         res.setHeader("Cache-Control""private");  
  67.         res.setHeader("Pragma""no-cache");  
  68.         PrintWriter writer = res.getWriter();  
  69.         // for IE  
  70.         writer.println("<!-- Comet is a programming technique that enables web servers to send data to the client without having any need for the client to request it. -->\n");  
  71.         writer.flush();  
  72.   
  73.         final AsyncContext ac = req.startAsync();  
  74.         ac.setTimeout(10  * 60 * 1000);  
  75.         ac.addListener(new AsyncListener() {  
  76.             public void onComplete(AsyncEvent event) throws IOException {  
  77.                 queue.remove(ac);  
  78.             }  
  79.   
  80.             public void onTimeout(AsyncEvent event) throws IOException {  
  81.                 queue.remove(ac);  
  82.             }  
  83.   
  84.             public void onError(AsyncEvent event) throws IOException {  
  85.                 queue.remove(ac);  
  86.             }  
  87.   
  88.             public void onStartAsync(AsyncEvent event) throws IOException {  
  89.             }  
  90.         });  
  91.         queue.add(ac);  
  92.     }  
  93.   
  94.     @Override  
  95.     @SuppressWarnings("unchecked")  
  96.     protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {  
  97.         res.setContentType("text/plain");  
  98.         res.setHeader("Cache-Control""private");  
  99.         res.setHeader("Pragma""no-cache");  
  100.   
  101.         req.setCharacterEncoding("UTF-8");  
  102.         String action = req.getParameter("action");  
  103.         String name = req.getParameter("name");  
  104.   
  105.         if ("login".equals(action)) {  
  106.             String cMessage = BEGIN_SCRIPT_TAG + toJsonp("System Message", name + " has joined.") + END_SCRIPT_TAG;  
  107.             notify(cMessage);  
  108.   
  109.             res.getWriter().println("success");  
  110.         } else if ("post".equals(action)) {  
  111.             String message = req.getParameter("message");  
  112.             String cMessage = BEGIN_SCRIPT_TAG + toJsonp(name, message) + END_SCRIPT_TAG;  
  113.             notify(cMessage);  
  114.   
  115.             res.getWriter().println("success");  
  116.         } else {  
  117.             res.sendError(422"Unprocessable Entity");  
  118.         }  
  119.     }  
  120.   
  121.     @Override  
  122.     public void destroy() {  
  123.         queue.clear();  
  124.         notifierThread.interrupt();  
  125.     }  
  126.   
  127.     private void notify(String cMessage) throws IOException {  
  128.         try {  
  129.             messageQueue.put(cMessage);  
  130.         } catch(Exception ex) {  
  131.             IOException t = new IOException();  
  132.             t.initCause(ex);  
  133.             throw t;  
  134.         }  
  135.     }  
  136.   
  137.     private String escape(String orig) {  
  138.         StringBuffer buffer = new StringBuffer(orig.length());  
  139.   
  140.         for (int i = 0; i < orig.length(); i++) {  
  141.             char c = orig.charAt(i);  
  142.             switch (c) {  
  143.             case '\b':  
  144.                 buffer.append("\\b");  
  145.                 break;  
  146.             case '\f':  
  147.                 buffer.append("\\f");  
  148.                 break;  
  149.             case '\n':  
  150.                 buffer.append("<br />");  
  151.                 break;  
  152.             case '\r':  
  153.                 // ignore  
  154.                 break;  
  155.             case '\t':  
  156.                 buffer.append("\\t");  
  157.                 break;  
  158.             case '\'':  
  159.                 buffer.append("\\'");  
  160.                 break;  
  161.             case '\"':  
  162.                 buffer.append("\\\"");  
  163.                 break;  
  164.             case '\\':  
  165.                 buffer.append("\\\\");  
  166.                 break;  
  167.             case '<':  
  168.                 buffer.append("&lt;");  
  169.                 break;  
  170.             case '>':  
  171.                 buffer.append("&gt;");  
  172.                 break;  
  173.             case '&':  
  174.                 buffer.append("&amp;");  
  175.                 break;  
  176.             default:  
  177.                 buffer.append(c);  
  178.             }  
  179.         }  
  180.   
  181.         return buffer.toString();  
  182.     }  
  183.   
  184.     private String toJsonp(String name, String message) {  
  185.         return "window.parent.update({ name: \"" + escape(name) + "\", message: \"" + escape(message) + "\" });\n";  
  186.     }  
  187. }  


ajax.js 
Java代码   收藏代码
  1. var count=0;  
  2. $(document).ready(function () {  
  3.      
  4.     var url='/ajax/chat';  
  5.     $('#login-name').focus();  
  6.   
  7.     $('#comet-frame')[0].src=url + '?' + count;  
  8.     count ++;  
  9.      
  10.     $("#login-button").click(function () {  
  11.             var name = $('#login-name').val();  
  12.             if(! name.length > 0) {  
  13.                 $('#system-message').css("color","red");  
  14.                 $('#login-name').focus();  
  15.                 return;  
  16.             }  
  17.             $('#system-message').css("color","#2d2b3d") ;  
  18.             $('#system-message').html(name + ':');  
  19.   
  20.             $('#login-button').disabled = true;  
  21.             $('#login-form').css("display","none");  
  22.             $('#message-form').css("display","");  
  23.   
  24.             var query =  
  25.             'action=login' +  
  26.             '&name=' + encodeURI($('#login-name').val());  
  27.             $.ajax({  
  28.                 type:"post",  
  29.                 url:url,  
  30.                 data:query,  
  31.                 success:function (data,status) {  
  32.                     $('#message').focus();  
  33.                 },  
  34.                 error:function () {  
  35.                     alert("error occured!!!");  
  36.                 }  
  37.             });  
  38.     });  
  39.       
  40.   
  41.     $("#post-button").click(function () {  
  42.         var message = $('#message').val();  
  43.         if(!message > 0) {  
  44.             return;  
  45.         }  
  46.         $('#message').disabled = true;  
  47.         $('#post-button').disabled = true;  
  48.   
  49.         var query =  
  50.         'action=post' +  
  51.         '&name=' + encodeURI($('#login-name').val()) +  
  52.         '&message=' + encodeURI(message);  
  53.         $.ajax({  
  54.             type:"post",  
  55.             url:url,  
  56.             data:query,  
  57.             success:function (data,status) {  
  58.                 $('#message').disabled = false;  
  59.                 $('#post-button').disabled = false;  
  60.                 $('#message').focus();  
  61.                 $('#message').val("");  
  62.             },  
  63.             error:function () {  
  64.                 alert("error occured!!!");  
  65.             }  
  66.         });  
  67.     }  
  68.     )  
  69. });  
  70.   
  71. function update(data){  
  72.     var p = document.createElement('p');  
  73.     p.innerHTML = data.name + ':<br/>' + data.message;  
  74.   
  75.     $('#display')[0].appendChild(p);  
  76. }  


index.html 
Java代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE html  
  3. PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  
  4. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
  5. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">  
  6.     <head>  
  7.         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
  8.         <title>Glassfish Chat</title>  
  9.         <link rel="stylesheet" href="css/default.css" type="text/css" />  
  10.         <script type="text/javascript" src="js/jquery-1.4.min.js"></script>  
  11.         <script type="text/javascript" src="js/ajax.js"></script>  
  12.     </head>  
  13.     <body>  
  14.         <div id="container">  
  15.             <div id="container-inner">  
  16.                 <div id="header">  
  17.                     <h1>Glassfish Chat</h1>  
  18.                 </div>  
  19.                 <div id="main">  
  20.                     <div id="display">  
  21.                     </div>  
  22.                     <div id="form">  
  23.                         <div id="system-message">Please input your name:</div>  
  24.                         <div id="login-form">  
  25.                             <input id="login-name" type="text" />  
  26.                             <br />  
  27.                             <input id="login-button" type="button" value="Login" />  
  28.                         </div>  
  29.                         <div id="message-form" style="display: none;">  
  30.                             <div>  
  31.                                 <textarea id="message" name="message" rows="2" cols="40"></textarea>  
  32.                                 <br />  
  33.                                 <input id="post-button" type="button" value="Post Message" />  
  34.                             </div>  
  35.                         </div>  
  36.                     </div>  
  37.                 </div>  
  38.             </div>  
  39.         </div>  
  40.         <iframe id="comet-frame" style="display: none;"></iframe>  
  41.     </body>  
  42. </html>  

servlet形成异步处理的过程 
  • 在init()方法里,开启一条线程从消息队列中读取消息,并且在AsyncContext(异步上下文)中处理这些消息  
    Java代码   收藏代码
    1. PrintWriter acWriter = ac.getResponse().getWriter();  
    2. acWriter.println(cMessage);  
    3. acWriter.flush();  

      前面的代码写入一个信息,每个异步请求对应AsyncContext。
  • 在doGet方法里,设置超时时间为10分钟,开始异步并且增加AsyncContext到队列中 
    Java代码   收藏代码
    1. final AsyncContext ac = req.startAsync();  
    2. ac.setTimeout(10 * 60 * 1000);  
    3. queue.add(ac);  

      对AsyncContext注册AsyncListener 监听器,在这种情况下,只有从队列中清理AsyncContext 
     
    Java代码   收藏代码
    1. ac.addListener(new AsyncListener() {  
    2.     public void onComplete(AsyncEvent event) throws IOException {  
    3.         queue.remove(ac);  
    4.     }  
    5.   
    6.     public void onTimeout(AsyncEvent event) throws IOException {  
    7.         queue.remove(ac);  
    8.     }  
    9.   
    10.     public void onError(AsyncEvent event) throws IOException {  
    11.         queue.remove(ac);  
    12.     }  
    13.   
    14.     public void onStartAsync(AsyncEvent event) throws IOException {  
    15.     }  
    16. });  
  • 在doPost方法里,将消息加入到消息队列里,消息在init方法里开启线程执行


    问题:不明白在ajax.js中为什么要加上$('#comet-frame')[0].src=url + '?' + count;这么一句,不加上的话,页面显示不了! 
    • ajax.rar (128.8 KB)
    • 下载次数: 167

    你可能感兴趣的:(servlet3.0的学习(二))