ITPub博客

首页 > 应用开发 > Java > 反向Ajax之WebSocket

反向Ajax之WebSocket

原创 Java 作者:壹頁書 时间:2013-12-27 00:09:35 0 删除 编辑
WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。

反向Ajax在观察者模型、聊天系统中应用的越来越多。如股票,监控等系统。

以聊天系统为例,如果没有服务器推的技术,Web聊天系统只能以固定的时间间隔轮询服务器。
这会产生大量的无用的连接,对服务器造成巨大压力。
在单位写过一个IM聊天系统,在配置了线程池,内存缓存等优化手段之后,通过loadrunner压力测试,并发访问量却始终超不过200/s。在这种系统中,轮询是一种噩梦。

WebSocket作为服务器推(反向Ajax)的手段之一,可以解决这种需求。
下面的例子,简单介绍了WebSocket的使用。
服务器每隔3秒,将自身的内存信息推送到所有连接的客户端浏览器。如果客户端浏览器点击按钮,则立即对该客户端返回最新的信息。
页面:
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>WebSocket</title>
  6. <script type="text/javascript"
  7.     src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
  8. <script type="text/javascript">
  9.     var ws = null;
  10.     function startWebSocket() {
  11.         if ('WebSocket' in window) {
  12.             ws = new WebSocket('ws://127.0.0.1:8080/Web/ws.do');
  13.         } else if ('MozWebSocket' in window) {
  14.             ws = new MozWebSocket('ws://127.0.0.1:8080/Web/ws.do');
  15.         } else {
  16.             alert('浏览器不支持WebSocket');
  17.         }

  18.         ws.onmessage = function(evt) {
  19.             $('#content').html(evt.data);
  20.         }

  21.         ws.onclose = function(evt) {
  22.             $('#content').html('WebSocket关闭');
  23.         }

  24.         ws.onopen = function(evt) {
  25.             $('#content').html('WebSocket已经打开');
  26.         }
  27.     }

  28.     function getJVMInfo() {
  29.         //随便发点什么
  30.         ws.send(new Date());
  31.     }

  32.     $(document).ready(function() {
  33.         startWebSocket();
  34.     });
  35. </script>
  36. </head>
  37. <body>
  38.     <input type="button" value="立即获取" onclick="getJVMInfo();" />
  39.     <div id="content"></div>
  40. </body>
  41. </html>
代码:

  1. import java.io.IOException;
  2. import java.net.URLDecoder;
  3. import java.net.URLEncoder;
  4. import java.nio.ByteBuffer;
  5. import java.nio.CharBuffer;
  6. import java.text.SimpleDateFormat;
  7. import java.util.Date;
  8. import java.util.List;
  9. import java.util.concurrent.CopyOnWriteArrayList;
  10. import java.util.concurrent.Executors;
  11. import java.util.concurrent.ScheduledExecutorService;
  12. import java.util.concurrent.TimeUnit;

  13. import javax.servlet.ServletException;
  14. import javax.servlet.annotation.WebServlet;
  15. import javax.servlet.http.HttpServlet;
  16. import javax.servlet.http.HttpServletRequest;
  17. import javax.servlet.http.HttpServletResponse;

  18. import org.apache.catalina.websocket.MessageInbound;
  19. import org.apache.catalina.websocket.StreamInbound;
  20. import org.apache.catalina.websocket.WebSocketServlet;
  21. import org.apache.catalina.websocket.WsOutbound;

  22. /**
  23.  * Servlet implementation class InitServlet
  24.  */
  25. @WebServlet("/ws.do")
  26. public class InitServlet extends WebSocketServlet implements Runnable {
  27.     List<JVMMessageInbound> list = new CopyOnWriteArrayList<JVMMessageInbound>();
  28.     ScheduledExecutorService singleThread = Executors.newSingleThreadScheduledExecutor();
  29.     {
  30.         singleThread.scheduleWithFixedDelay(this, 3, 3, TimeUnit.SECONDS);
  31.     }

  32.     @Override
  33.     protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest arg1) {
  34.         return new JVMMessageInbound();
  35.     }

  36.     private class JVMMessageInbound extends MessageInbound {

  37.         @Override
  38.         protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
  39.         }

  40.         @Override
  41.         protected void onTextMessage(CharBuffer arg0) throws IOException {
  42.             CharBuffer cb = CharBuffer.wrap(arg0);
  43.             String data = cb.toString();
  44.             System.out.println(data);
  45.             this.getWsOutbound().writeTextMessage(CharBuffer.wrap(getJVMInfo()));
  46.             this.getWsOutbound().flush();
  47.         }

  48.         @Override
  49.         protected void onClose(int status) {
  50.             System.out.println("Close WebSocket");
  51.             super.onClose(status);
  52.             list.remove(this);
  53.         }

  54.         @Override
  55.         protected void onOpen(WsOutbound outbound) {
  56.             System.out.println("Open new WebSocket");
  57.             super.onOpen(outbound);
  58.             list.add(this);
  59.         }

  60.     }

  61.     private String getJVMInfo() {
  62.         long useMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
  63.         useMemory = useMemory / 1024;
  64.         return "已用内存:" + String.valueOf(useMemory) + "K";
  65.     }

  66.     @Override
  67.     public void run() {
  68.         System.out.println("发送广播通知");
  69.         String data = "广播通知\n" + new Date() + "\n" + getJVMInfo();
  70.         for (JVMMessageInbound m : list) {
  71.             try {
  72.                 m.getWsOutbound().writeTextMessage(CharBuffer.wrap(data));
  73.                 m.getWsOutbound().flush();
  74.             } catch (IOException e) {
  75.                 e.printStackTrace();
  76.             }
  77.         }
  78.     }

  79. }
效果截图:

但是在Tomcat 7.0.47版本中,WebSocketServlet已经标识为deprecated,并可能在Tomcat 8中remove。
是不是设计了更好的API



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-1064838/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 裁剪树
请登录后发表评论 登录
全部评论

注册时间:2013-10-19

  • 博文量
    620
  • 访问量
    6339850