websocket技术分享
开发环境:
spring3+tomcat7+spring-websocket4 + spring security3
运行环境:
windows、Linux
一、背景:
产品将要发布的消息或其他需要让客户提前知道的消息,在客户端和服务端建立连接后推送
给客户端。
二、WebSocket是什么
WebSocket协议是基于TCP的一种新的网络协议。
三、WebSocket身世挖掘
1、WebSocket是HTML5出的东西(协议),跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已

2、HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个
3、Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说
4、典型的Websocket握手

| Chrome | Supported in version 4+ | 
| Firefox | Supported in version 4+ | 
| Opera | Supported in version 10+ | 
| Safari | Supported in version 5+ | 
| IE(Internet Explorer) | Supported in version 10+ | 
四、WebSocket的特点
1、长连接,实现双向通信, 具有底层socket的特点,实现真正意义上的推送功能。
2、是HTML5的技术之一,具有巨大的应用前景
3、节约带宽,节省服务器资源
缺点:
少部分浏览器不支持,浏览器支持的程度与方式有区别
五、WebSocket如何用
前端代码:
 var DJCW_webSocket = (function(){
     var webSocket = null,
         tryTime = 0,
         initSocket;
     initSocket = function(){
         debugger
         var _marquee = "<marquee behavior='scroll' direction='left' behavior='scroll'>";
         if (!window.WebSocket) {
             alert("您的浏览器不支持websocket!");
             return false;
         }
         webSocket = new WebSocket('ws://127.0.0.1:8082/projectname/websocket');
         // 收到服务端消息
         webSocket.onmessage = function(msg) {
             DJCW.messagesScroll(msg.data);
         };
         // 异常
         webSocket.onerror = function(event) {};
         // 建立连接
         webSocket.onopen = function(event) {};
         // 断线重连
         webSocket.onclose = function() {
             // 重试10次,每次之间间隔10秒
             if (tryTime < 10) {
                 setTimeout(function() {
                     webSocket = null;
                     tryTime++;
                     initSocket();
                 }, 500);
             } else {
                 tryTime = 0;
             }
         };
     };
     initModule =  function() {
         initSocket();
     };
     return {
         initSocket:initSocket,
         initModule : initModule
     };
 })();
 $(function() {
     DJCW_webSocket.initModule();
     window.onbeforeunload = function() {
         // 离开页面时的其他操作
     };
 });
后端代码:
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint; import org.springframework.stereotype.Service; /**
* 功能说明:websocket处理类, 使用J2EE7的标准 切忌直接在该连接处理类中加入业务处理代码 作者:ydd(2017-04-12 15:29)
*/
// relationId和userCode是我的业务标识参数,websocket是连接的路径,可以自行定义
@ServerEndpoint("/websocket")
@Service
public class WebsocketEndPoint { private static final Log LOG = Log.getLogger(WebsocketEndPoint.class); private static CopyOnWriteArraySet<WebsocketEndPoint> sessions = new CopyOnWriteArraySet<WebsocketEndPoint>();
private Session session; public WebsocketEndPoint() {
} /**
* @Title: onOpen
* @Description: (打开连接时触发)
* @param @param session 设定文件
* @return void 返回类型
* @throws
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
sessions.add(this);
} /**
* @Title: onMessage
* @Description: (收到客户端消息时触发)
* @param @param message
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
@OnMessage
public String onMessage(String message) {
return "Got your message (" + message + ").Thanks !";
} /**
* @Title: onError
* @Description: (异常时触发)
* @param @param throwable
* @param @param session 设定文件
* @return void 返回类型
* @throws
*/
@OnError
public void onError(Throwable throwable, Session session) {
LOG.e("Chat Error: " + throwable.toString());
} /**
* @Title: onClose
* @Description: (关闭连接时触发)
* @param @param session 设定文件
* @return void 返回类型
* @throws
*/
@OnClose
public void onClose(Session session) {
sessions.remove(this);
} /**
* 向所有用户发送消息
*
* @param msg
*/
public void sendUser(String msg) {
try {
if (sessions.size() != 0) {
for (WebsocketEndPoint s : sessions) {
if (s != null) {
s.session.getBasicRemote().sendText(msg);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
} }
六、WebSocket应用场景
在线聊天室、在线客服系统、评论系统、WebIM等
七、WebSocket的实现原理
 
WebSocket和传统的HTTP交互方式的区别如下图:
八、遇到的错误
<!-- spring security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<!-- 由于加入了websocket,不能写成/*,不然会出现302循环重定向,因为和 DispatcherServlet相冲突-->
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>*.js</url-pattern>
<url-pattern>*.jsp</url-pattern>
<!--通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()可以获取到用户名 -->
<url-pattern>/login/</url-pattern>
<!-- 登录时springsecurity自带的类进行用户密码认证以及赋予相关权限 -->
<url-pattern>/j_spring_security_check</url-pattern>
<!-- 退出时通过springsecurity自带的url进行退出并清除session -->
<url-pattern>/j_spring_security_logout</url-pattern>
</filter-mapping>
九、头脑风暴
1、在同一浏览器同时打开同一产品带有ws协议请求的多个标签页,是否都会走onClose方法(即删除相应的session)
经测试是会的
2、static CopyOnWriteArraySet<WebsocketEndPoint> sessions = new CopyOnWriteArraySet<WebsocketEndPoint>();
每次加载类的时候不会new出一个新的实例吗,这样的话怎么实现的将消息推送给所有用户呢
不会每次都new出一个新的实例
static变量
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。
两者的区别是:
  对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),
当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
CopyOnWriteArraySet介绍:
属于java.util.concurrent包下的,java.util.concurrent 包添加了多个新的线程安全集合类(ConcurrentHashMap、CopyOnWriteArrayList 和
CopyOnWriteArraySet)这些类的目的是提供高性能、高度可伸缩性、线程安全的基本集合类型版本,通过同步的封装工厂(Collections.synchronizedMap()、
synchronizedList() 和 synchronizedSet()),非线程安全集合均可表现为线程安全的
websocket技术分享的更多相关文章
- 好程序员技术分享html5和JavaScript的区别
		好程序员技术分享html5和JavaScript的区别,HTML5广义上讲是前端开发学科的代名词,包含HTML5.CSS3及JavaScript三个重要的部分,是运行在浏览器上应用的统称.如PC端网站 ... 
- 腾讯技术分享:微信小程序音视频技术背后的故事
		1.引言 微信小程序自2017年1月9日正式对外公布以来,越来越受到关注和重视,小程序上的各种技术体验也越来越丰富.而音视频作为高速移动网络时代下增长最快的应用形式之一,在微信小程序中也当然不能错过. ... 
- 融云技术分享:融云安卓端IM产品的网络链路保活技术实践
		本文来自融云技术团队原创分享,原文发布于“ 融云全球互联网通信云”公众号,原题<IM 即时通讯之链路保活>,即时通讯网收录时有部分改动. 1.引言 众所周知,IM 即时通讯是一项对即时性要 ... 
- fir.im Weekly - 新开发时代,需要什么样的技术分享
		"2016年,当我们迎来了如Xcode 8.Swift 3.SiriKit.Android N.Android Instant Apps.React Native等诸多移动开发技术.开发工具 ... 
- 【转发】网易邮箱前端技术分享之javascript编码规范
		网易邮箱前端技术分享之javascript编码规范 发布日期:2013-11-26 10:06 来源:网易邮箱前端技术中心 作者:网易邮箱 点击:533 网易邮箱是国内最早使用ajax技术的邮箱.早在 ... 
- HTML5 WebSocket 技术介绍
		WebSocket是html5规范新引入的功能,用于解决浏览器与后台服务器双向通讯的问题,使用WebSocket技术,后台可以随时向前端推送消息,以保证前后台状态统一,在传统的无状态HTTP协议中,这 ... 
- CDN技术分享
		CDN技术分享目录 网络应用服务发展 CDN技术 1.CDN是什么?为什么我们需要它?(简介) 2.CDN能做什么?(作用) 3.CDN是如何工作?(原理) 4.CDN有那些具体应用?(应用) 我们项 ... 
- WebSocket技术
		webSocket技术 在html5技术革新中,加入了WebSocket技术 1.webSocket实际是TCP连接 webSocket在最初将发送http连接请求到服务器端, 但是在header中加 ... 
- 【转】apache kafka技术分享系列(目录索引)
		转自: http://blog.csdn.net/lizhitao/article/details/39499283 估计大神会不定期更新,所以还是访问这个链接看最新的目录list比较好 apa ... 
随机推荐
- HTML 5入门知识——Drag
			HTML 5拖放 拖放的步骤: 1.对象元素的draggable属性设置为true,还需要注意的是a元素和img元素必须指定href. 2.编写与拖放有关的事件处理代码: DataTransfer对象 ... 
- Mditor 发布「桌面版」了 - http://mditor.com
			简单说明 Mditor 最早只有「组件版」,随着「桌面版」的发布,Mditor 目前有两个版本: 可嵌入到任意 Web 应用的 Embed 版本,这是一桌面版的基础,Repo: https://git ... 
- MSTP多实例的配置
			MSTP多实例的配置 这次实验主要是为了加强对stp生成树协议中,RP(根端口),DP(指定端口),AP(阻塞端口)的判断方法:虽然很多时候不需要我们人工判断,因为当我们吧所有的配置好之后,然后开启生 ... 
- Spring Data操作Redis详解
			Spring Data操作Redis详解 Redis是一种NOSQL数据库,Key-Value形式对数据进行存储,其中数据可以以内存形式存在,也可以持久化到文件系统.Spring data对Redis ... 
- JQ万能轮播图
			lunbotu.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ... 
- Android开发之Bitmap的高效加载
			BitmapFactory类提供了四类方法:decodeFile, decodeResource, decodeStream和decodeByteArray 分别用于支持从文件系统,资源,输入流以及字 ... 
- iOS开发之@Selector参数的传递
			比如: NSMutableDictionary *dic = [[NUMutableDictionary alloc]init]; [dic setValue:@”haha” forKey:@”tes ... 
- Python 获取 网易云音乐热门评论
			最近在研究文本挖掘相关的内容,所谓巧妇难为无米之炊,要想进行文本分析,首先得到有文本吧.获取文本的方式有很多,比如从网上下载现成的文本文档,或者通过第三方提供的API进行获取数据.但是有的时候我们想要 ... 
- Spark踩坑记——共享变量
			[TOC] 前言 Spark踩坑记--初试 Spark踩坑记--数据库(Hbase+Mysql) Spark踩坑记--Spark Streaming+kafka应用及调优 在前面总结的几篇spark踩 ... 
- Eric的第一天
			我叫刘志扬(ERIC),今天第一次来博客园,我是一个爱编程的小子,我使用开发工具Androidstudio(AS)我要把今后的问题记录在博客园里,欢迎大家点评,吐槽. 
