场景

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. ORA-04031错误导致宕机案例分析

    今天遇到一起ORACLE数据库宕机案例,下面是对这起数据库宕机案例的原因进行分析.解读.分析过程中顺便记录一下这个案例的前因后果,攒点经验值,培养一下分析.解决问题的能力. 案例环境:   操作系统 ...

  2. Protocol 编码的三种常用方式

    1.使用固定长度 2.使用固定长度的请求头,请求头中说明了body的长度. 例如HTTP 协议: http请求协议: http 响应协议: 3.使用界定符.例如有很多基于text(文本)协议都会在每个 ...

  3. SSRS 的简单使用(一)

    简介 SQL Server Reporting Services(SSRS),微软企业级报表平台,和SQL Server Integration Service以及SQL Server Analysi ...

  4. Python基础之装饰器

    1.什么是装饰器? Python的装饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西.虽然 ...

  5. Linux计时器

    Linux中, 系统为每个系统都维护了三种计时器,分别为: 真实计数器, 虚拟计时器以及实用计时器, 一般情况下都使用真实计时器 getitimer()/setitimer() //读取/设置内部计时 ...

  6. JavaScript中的函数表达式

    在JavaScript中,函数是个非常重要的对象,函数通常有三种表现形式:函数声明,函数表达式和函数构造器创建的函数. 本文中主要看看函数表达式及其相关的知识点. 函数表达式 首先,看看函数表达式的表 ...

  7. [转] cordova-plugin-x-toast

    本文转自:https://www.npmjs.com/package/cordova-plugin-x-toast cordova plugin add https://github.com/Eddy ...

  8. ImageMagick Remote Command Execute

    CVE ID: CVE-2016-3714 我挺纠结应该用中文写博客还是应该用英文写博客.英文吧作用挺明显的,可以锻炼自己的英语表达能力,但是可能会阻碍和一些英文不好的朋友交流. It's upset ...

  9. CodeForces 466E Information Graph --树形转线性+并查集

    题意:有三种操作: 1.新增一条边从y连向x,此前x没有父节点 2.x接到一份文件,(文件标号逐次递增),然后将这份文件一路上溯,让所有上溯的节点都接到这份文件 3.查询某个节点x是否接到过文件F 解 ...

  10. 网络之Ip地址

    0.0.0.0---255.255.255.255 Ip地址分类(D.E)不对外开放 网络类别 最大网络数 IP地址范围(,唯一的,花钱的) 最大主机数 私有IP地址范围 (做内网ip,不可直接访问公 ...