场景

websocket是Html5新增加特性之一,目的是浏览器与服务端建立全双工的通信方式,解决http请求-响应带来过多的资源消耗,同时对特殊场景应用提供了全新的实现方式,比如聊天、股票交易、游戏等对对实时性要求较高的行业领域。

背景

在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。目前各大主流浏览器都支持websocket,IE浏览器要IE10+

一、POM依赖

POM依赖,spring4.1.4.RELEASE,spring核心依赖请自行添加,下面是websocket相关jar

<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>

二、WebSocket入口

@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//允许连接的域,只能以http或https开头
String[] allowsOrigins = {"http://www.xxx.com"}; //WebIM WebSocket通道
registry.addHandler(chatWebSocketHandler(),"/ webSocketIMServer").setAllowedOrigins(allowsOrigins).addInterceptors(myInterceptor());
registry.addHandler(chatWebSocketHandler(), "/sockjs/w ebSocketIMServer").setAllowedOrigins(allowsOrigins).addInterceptors(myInterceptor()).withSockJS();
}
@Bean
public ChatWebSocketHandler chatWebSocketHandler() {
return new ChatWebSocketHandler();
}
@Bean
public WebSocketHandshakeInterceptor myInterceptor(){
return new WebSocketHandshakeInterceptor();
}
}
  1. 实现WebSocketConfigurer接口,重写registerWebSocketHandlers方法,这是一个核心实现方法,配置websocket入口,允许访问的域、注册Handler、SockJs支持和拦截器。
  2. registry.addHandler注册和路由的功能,当客户端发起websocket连接,把/path交给对应的handler处理,而不实现具体的业务逻辑,可以理解为收集和任务分发中心。
  3. setAllowedOrigins(String[] domains),允许指定的域名或IP(含端口号)建立长连接,如果只允许自家域名访问,这里轻松设置。如果不限时使用"*"号,如果指定了域名,则必须要以http或https开头。
  4. addInterceptors,顾名思义就是为handler添加拦截器,可以在调用handler前后加入我们自己的逻辑代码。
  5. spring websocket也支持STOMP协议,下回再分享。

三、拦截器实现

public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {

    @Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object
> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
attributes.put("username",userName);
}
return true;
} @Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { }
}

beforeHandshake,在调用handler前处理方法。常用在注册用户信息,绑定WebSocketSession,在handler里根据用户信息获取WebSocketSession发送消息。

四、Handler处理类

public class ChatWebSocketHandler extends TextWebSocketHandler{

	private final static List<WebSocketSession> sessions = Collections.synchronizedList(new ArrayList<WebSocketSession>());
//接收文本消息,并发送出去
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
chatTextMessageHandler(message.getPayload());
super.handleTextMessage(session, message);
}
//连接建立后处理
@SuppressWarnings("unchecked")
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
logger.debug("connect to the websocket chat success......");
sessions.add(session);
//处理离线消息
}
//抛出异常时处理
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if(session.isOpen()){
session.close();
}
logger.debug("websocket chat connection closed......");
sessions.remove(session);
}
//连接关闭后处理
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
logger.debug("websocket chat connection closed......");
sessions.remove(session);
} @Override
public boolean supportsPartialMessages() {
return false;
}
}

五、客户端连接

var host = window.location.host;
var websocket;
if ('WebSocket' in window) {
websocket = new ReconnectingWebSocket("ws://"
+ host + "/webSocketIMServer", null, {debug:true, maxReconnectAttempts:4});
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://" + host
+ "/webSocketIMServer");
} else {
websocket = new SockJS("http://" + host
+ "/sockjs/webSocketIMServer");
}
websocket.onopen = function(evnt) {
console.log("websocket连接上");
};
websocket.onmessage = function(evnt) {
messageHandler(evnt.data);
};
websocket.onerror = function(evnt) {
console.log("websocket错误");
};
websocket.onclose = function(evnt) {
console.log("websocket关闭");
}

这里用到了ReconnectingWebSocket.js,对浏览器自带websocket添加了扩展,例如重连,连接超时时间,失败重连间隔,尝试连接最大次数等。

项目主页:ReconnectingWebSocket

ps:如果有疑问,你也可以关注我的微信公众号『ITNotes』, 一起交流学习 。

spring WebSocket详解的更多相关文章

  1. Spring配置文件详解 – applicationContext.xml文件路径

    Spring配置文件详解 – applicationContext.xml文件路径 Java编程                 spring的配置文件applicationContext.xml的默 ...

  2. spring配置文件详解--真的蛮详细

    spring配置文件详解--真的蛮详细   转自: http://book.51cto.com/art/201004/193743.htm 此处详细的为我们讲解了spring2.5的实现原理,感觉非常 ...

  3. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

  4. J2EE进阶(四)Spring配置文件详解

    J2EE进阶(四)Spring配置文件详解 前言 Spring配置文件是用于指导Spring工厂进行Bean生产.依赖关系注入(装配)及Bean实例分发的"图纸".Java EE程 ...

  5. Spring RestTemplate详解

    Spring RestTemplate详解   1.什么是REST? REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格 ...

  6. spring事务详解(五)总结提高

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.概念 ...

  7. spring事务详解(四)测试验证

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  8. spring事务详解(二)简单样例

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  9. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

随机推荐

  1. 在网页中显示CHM (c# csharp .net asp.net winform)

    CHM即“已编译的帮助文件”,主要由.hhc(目录文件)..hhk(索引文件)以及相应的帮助主题文件(.html,.htm)这些内容编译而成. 方法对比 在网页中显示CHM内容,大致有以下几种办法: ...

  2. VS.net 2013中使用Git建立源代码管理 版本管理

    第一次在VS2013中使用Git,也是第一次使用Git,各种不熟悉.百度各种使用经验,大都不屑于使用VS2013集成的Git,建议下载这个下载那个,我也照学了,确实能实现项目的提交.同步.合并的工作, ...

  3. Apache安装

    记录安装Apache的流程,没有进行详细配置,只是记录搭建服务器的流程用于学习Ajax等知识,方便以后重新安装,不用每次都翻别人博客学习安装了,大神看到这里可以关掉这个粗糙简陋的博文了. 1. 官网上 ...

  4. pentaho cde 封装自定义图形控件,动态传参

    在实际项目中经常会用到将经常用到的图形表格组成一个控件,其他地方直接调用,类似于服务器开发的接口,而现在就需要将一些常用的图形做封装,这样就不必重复多次创建相同的内容. 下面就简单的定义一个自定义柱形 ...

  5. SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行)

    前言 前面几篇我们分析了关于SQL Server关于性能调优的一系列内容,我把它分为两个模块. 第一个模块注重基础内容的掌握,共分7篇文章完成,内容涵盖一系列基础运算算法,详细分析了如何查看执行计划. ...

  6. JS MD5

    1 /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as ...

  7. 敲-PHP与MySQL,JSON

    hi 敲代码~ 1.php与mysql 5.4 修改界面 同样是界面和程序. 界面article.modify.php <?php require_once('../connect.php'); ...

  8. Java与模式读书笔记

    >设计目标:可扩展性,灵活性,可插入性. >设计原则 ● Open Closed Principle 开闭原则 对扩展开放,对修改关闭. 对面向对象的语言来说,不可以更改的是系统的抽象层, ...

  9. TopCoder SRM 642 Div.2 1000 --二分+BFS

    题意: 给你一张图,N个点(0~N-1),m条边,国王要从0到N-1,国王携带一个值,当走到一条边权大于此值的边时,要么不走,要么提升该边的边权,提升k个单位花费k^2块钱,国王就带了B块钱,问能携带 ...

  10. Qt5 发布的exe应用程序Windows下无法执行的问题解决方案

    本解决方案着重解决报错为: This application has requested the Runtime to terminate it in an unusual way. 的错误. 即: ...