一、写在前面

   要求做一个,后台发布信息,前台能即时得到通知的消息推送功能。网上搜了也有很多方式,ajax的定时询问,Comet方式,Server-Sent方式,以及websocket。表示除了定时询问外,就websocket相对简单点。

二、实现

  实现类java代码:

  1. package cn.xm.mall.websocket.controller;
  2.  
  3. import java.io.IOException;
  4. import java.nio.ByteBuffer;
  5. import java.nio.CharBuffer;
  6. import java.text.SimpleDateFormat;
  7. import java.util.Date;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. import java.util.Set;
  11.  
  12. import javax.servlet.annotation.WebServlet;
  13. import javax.servlet.http.HttpServletRequest;
  14.  
  15. import org.apache.catalina.websocket.MessageInbound;
  16. import org.apache.catalina.websocket.StreamInbound;
  17. import org.apache.catalina.websocket.WebSocketServlet;
  18. import org.apache.catalina.websocket.WsOutbound;
  19.  
  20. @WebServlet("/webSocket.do")
  21. public class WebSocketServletController extends WebSocketServlet {
  22. private final Map<Integer, WsOutbound> map = new HashMap<Integer, WsOutbound>();
  23. private static final long serialVersionUID = -1058445282919079067L;
  24. @Override
  25. protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest request) {
  26. // StreamInbound:基于流的WebSocket实现类(带内流),应用程序应当扩展这个类并实现其抽象方法onBinaryData和onTextData。
  27. return new ChatMessageInbound();
  28. }
  29. class ChatMessageInbound extends MessageInbound {
  30. // MessageInbound:基于消息的WebSocket实现类(带内消息),应用程序应当扩展这个类并实现其抽象方法onBinaryMessage和onTextMessage。
  31. @Override
  32. protected void onOpen(WsOutbound outbound) {
  33. map.put(outbound.hashCode(), outbound);
  34. super.onOpen(outbound);
  35. }
  36. @Override
  37. protected void onClose(int status) {
  38. map.remove(getWsOutbound().hashCode());
  39. super.onClose(status);
  40. }
  41. @Override
  42. protected void onBinaryMessage(ByteBuffer buffer) throws IOException {
  43. }
  44. @Override
  45. protected void onTextMessage(CharBuffer buffer) throws IOException {
  46. String msg = buffer.toString();
  47. Date date = new Date();
  48. SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
  49. //msg = " <font color=green>匿名用戶 " + sdf.format(date) + "</font><br/> " + msg;
  50. broadcast(msg);
  51. }
  52. private void broadcast(String msg) {
  53. Set<Integer> set = map.keySet();
  54. for (Integer integer : set) {
  55. WsOutbound outbound = map.get(integer);
  56. CharBuffer buffer = CharBuffer.wrap(msg);
  57. try {
  58. outbound.writeTextMessage(buffer);
  59. outbound.flush();
  60. } catch (IOException e) {
  61. e.printStackTrace();
  62. }
  63. }
  64. }
  65. }
  66. }

前台连接websocket 代码 写到了js里,页面直接引用,就和websocket连通了。

  1. /**
  2. * WebSocket消息推送
  3. * @Copyright Copyright (c) 2006
  4. * @author Guapo
  5. * @see DESCore
  6. */
  7. $(function() {
  8. var loginNameCookie=$.cookie('memberInfo');
  9. if(typeof(loginNameCookie) == "undefined" || loginNameCookie==null || loginNameCookie==''){}else{
  10. chat();
  11. }
  12.  
  13. });
  14.  
  15. var socket;
  16.  
  17. var chat = function() {
  18.  
  19. socket = new WebSocket('ws://XXXXX/webSocket.do');
  20.  
  21. socket.onopen = function(event) {
  22.  
  23. console.info("<font color=green>连接成功!</font>");
  24.  
  25. };
  26. socket.onmessage = function(event) {
  27. if("pms"==event.data){
  28. appendInsideLetter();//这里是后台send一个pms参数类型,前台得知后,异步查询后台通知的资讯,然后页面通知动作的方法
  29. }
  30. };
  31.  
  32. socket.onclose = function(event) {
  33. console.info("<font color=green>连接断开!</font>");
  34.  
  35. };
  36. if (socket == null) {
  37. console.info("<font color=green>连接失败!</font>");
  38.  
  39. }
  40. };
  41. var send = function() {

后台同理和前台连接同一个websoket后。在发布完信息后,调用一下send方法。代码如下

  1. var socket;
  2.  
  3. var chat = function() {
  4.  
  5. socket = new WebSocket('ws://www.simaakj.com/webSocket.do');
  6.  
  7. socket.onopen = function(event) {
  8. console.info("<font color=green>连接成功!</font>");
  9. send();//后台连接的时候,就通知了一下。
  10.  
  11. };
  12. socket.onmessage = function(event) {
  13.  
  14. };
  15.  
  16. socket.onclose = function(event) {
  17. console.info("<font color=green>连接断开!</font>");
  18.  
  19. };
  20. if (socket == null) {
  21. console.info("<font color=green>连接失败!</font>");
  22.  
  23. }
  24. };
  25. var send = function() {
  26.  
  27. socket.send("pms");
  28.  
  29. }

后台操作完,调用 chat();既可推送告知前台成功。

三、遇到的问题,总结

  0、The hierarchy of the type MyMessageInbound is inconsistent。一开始遇到这个问题,原因是缺少包,不仅仅需要tomcat中的catalina.jar以及websocket-api.jar。还需要tomcat-coyote-7.0.27.jar

  1、以上代码放到本地后,开发发现连不上,发现需要在登录过滤把webSocket.do去掉,去掉之后,本地运行好使了。

  2、放到环境中后,发现又有问题,原来是环境用到了Nginx,导致websoket不好使,百度了下解决办法,在Nginx配置中加入以下代码,就好使了。

  我是在reverse-proxy.conf中添加的 

  1. proxy_http_version 1.1;
  2. proxy_set_header Upgrade $http_upgrade;
  3. proxy_set_header Connection "upgrade";

拾人牙慧篇之——基于HTML5中websocket来实现消息推送功能的更多相关文章

  1. ZH奶酪:基于ionic.io平台的ionic消息推送功能实现

    Hybrid App越来越火,Ionic的框架也逐渐被更多的人熟知. 在mobile app中,消息推送是很必要的一个功能. 国内很多ionic应用的推送都是用的极光推送,最近研究了一下Ionic自己 ...

  2. 基于ajax与msmq技术的消息推送功能实现

    周末在家捣鼓了一下消息推送的简单例子,其实也没什么技术含量,欢迎大伙拍砖.我设计的这个推送demo是基于ajax长轮询+msmq消息队列来实现的,具体交互过程如下图: 先说说这个ajax长轮询,多长时 ...

  3. springboot+websocket+sockjs进行消息推送【基于STOMP协议】

    springboot+websocket+sockjs进行消息推送[基于STOMP协议] WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就 ...

  4. WinForm中 Asp.Net Signalr消息推送测试实例

    p{ text-align:center; } blockquote > p > span{ text-align:center; font-size: 18px; color: #ff0 ...

  5. Worktile中百万级实时消息推送服务的实现

    Worktile中百万级实时消息推送服务的实现 出自:http://blog.jobbole.com/81125/

  6. 基于FCM的消息推送功能

    需求背景 我方项目需要支持客户端消息推送,iOS终端可以借由苹果本身的apns很方便的实现,但是对于Android来说,必须集成第三方的SDK来处理.考虑到项目需要以及成本,我们选择使用谷歌的FCM框 ...

  7. HTML5中的SSE(服务器推送技术)

    本文原链接:https://cloud.tencent.com/developer/article/1194063 SSE技术详解:一种全新的HTML5服务器推送事件技术 前言 概述 基本介绍 与We ...

  8. springboot整合websocket实现一对一消息推送和广播消息推送

    maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  9. mqtt协议实现 java服务端推送功能(三)项目中给多个用户推送功能

    接着上一篇说,上一篇的TOPIC是写死的,然而在实际项目中要给不同用户 也就是不同的topic进行推送 所以要写活 package com.fh.controller.information.push ...

随机推荐

  1. 清除行内元素之间的HTML空白

    原文连接:Remove Whitespace Between Inline-Block Elements 原文日期: 2013年8月27日 翻译日期: 2013年8月28日 至今我还记得年轻是在IE6 ...

  2. mysql聚集索引

    转自http://www.cnblogs.com/tuyile006/archive/2009/08/28/1555615.html 微软的SQL SERVER提供了两种索引:聚集索引(cluster ...

  3. 【面试必备】Swift&nbsp;面试题及其答案

    原文:Swift Interview Questions and Answers 原作者:Antonio Bello 原作者介绍: Antonio 拥有丰富的编程经验.他开始编程的时候,内存单位还是 ...

  4. Android studio使用git-android学习之旅(79)

    首先我参考了hello_my_show和梦痕_sky的博客,表示感谢 android studio对于git的支持是很好的,这节课我们拉讲解怎么使用git可视化工具来clone project和提交修 ...

  5. 【面试笔试算法】牛客网一站通Offer编程题2016.4.19

    牛客网一站通offer (一)字符串变形 1. 题目: 对于一个给定的字符串,我们需要在线性(也就是O(n))的时间里对它做一些变形.首先这个字符串中包含着一些空格,就像"Hello Wor ...

  6. uGUI使用代码动态添加Button.OnClick()事件(Unity3D开发之十二)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/42705885 ...

  7. VS2005的数据断点功能

    多年前在VS2005强大的条件断点功能里面讨论过VS2005的条件断点功能. 其实在VS2005里面还有比较好用的(为什么我不用很牛逼呢?因为和OD比起来实在是太简陋了,但是使用上还是比较方便的)内存 ...

  8. TrueType和Bitmap字体的区别

    只要标签的文本从不变化,在cocos2D中渲染TrueType和bitmap字体的性能是相同的.它们都仅仅像精灵那样绘制. 如果你希望大量的标签使用相同字体,则bitmap字体将更快.因为bitmap ...

  9. 通过服务修改widgetUI

    public static void updateAppWidget(Context context, String displayMsg) { AppWidgetManager appWidgetM ...

  10. LeetCode之“数学”:Rectangle Area

    题目链接 题目要求: Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle i ...