1.导入maven依赖

        <!-- websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>

2.创建类 HandshakeInterceptor 继承 HttpSessionHandshakeInterceptor

public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception { /**
* 在拦截器内强行修改websocket协议,将部分浏览器不支持的 x-webkit-deflate-frame 扩展修改成
* permessage-deflate
*/
if (request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {
request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
}
String jspCode = ((ServletServerHttpRequest) request).getServletRequest().getParameter("jspCode");
if (jspCode != null) {
attributes.put("jspCode", jspCode);
} else {
return false;
}
return true;
} @Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
super.afterHandshake(request, response, wsHandler, ex);
}
}

3.创建类 MyWebSocketConfig 继承 WebMvcConfigurerAdapter 并实现 WebSocketConfigurer

@Component
@EnableWebMvc
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Resource
MyWebSocketHandler handler; @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// TODO Auto-generated method stub
registry.addHandler(handler, "/websocket").addInterceptors(new HandshakeInterceptor());
registry.addHandler(handler, "/websocket/sockjs").addInterceptors(new HandshakeInterceptor()).withSockJS();
}
}

4.创建类 MyWebSocketHandler 实现 WebSocketHandler

@Component
public class MyWebSocketHandler implements WebSocketHandler { public static final Map<String, WebSocketSession> userSocketSessionMap; static {
userSocketSessionMap = new HashMap<String, WebSocketSession>();
} @Override
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
// TODO Auto-generated method stub
String jspCode = session.getId() + "-" + (String) session.getHandshakeAttributes().get("jspCode"); if (userSocketSessionMap.get(jspCode) == null) {
System.out.println("添加会话:" + jspCode);
userSocketSessionMap.put(jspCode, session);
}
} @Override
public void handleMessage(WebSocketSession session,
WebSocketMessage<?> message) throws Exception {
// TODO Auto-generated method stub
session.sendMessage(message);
} @Override
public void handleTransportError(WebSocketSession session,
Throwable exception) throws Exception {
// TODO Auto-generated method stub
if (session.isOpen()) {
session.close();
}
Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
// 移除Socket会话
while (it.hasNext()) {
Entry<String, WebSocketSession> entry = it.next();
if (entry.getValue().getId().equals(session.getId())) {
userSocketSessionMap.remove(entry.getKey());
System.out.println("Socket会话已经移除:用户ID:" + entry.getKey());
break;
}
}
} @Override
public void afterConnectionClosed(WebSocketSession session,
CloseStatus closeStatus) throws Exception {
// TODO Auto-generated method stub
System.out.println("Websocket:" + session.getId() + "已经关闭");
Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
// 移除Socket会话
while (it.hasNext()) {
Entry<String, WebSocketSession> entry = it.next();
if (entry.getValue().getId().equals(session.getId())) {
userSocketSessionMap.remove(entry.getKey());
System.out.println("Socket会话已经移除:用户ID:" + entry.getKey());
break;
}
}
} @Override
public boolean supportsPartialMessages() {
// TODO Auto-generated method stub
return false;
}
}

5.前段使用

<!-- websocket -->
<script type="text/javascript">
$(function() { var jspCode = "${user.userId}"; var websocket;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/ebcrawler/websocket?jspCode=" + jspCode);
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:8080/ebcrawler/websocket?jspCode=" + jspCode);
} else {
websocket = new SockJS("http://localhost:8080/ebcrawler/websocket/sockjs?jspCode=" + jspCode);
} websocket.onopen = function(event) {
$(".commonMsg").each(function() {
$(this).html($(this).html() + "已连接<br/>")
});
};
websocket.onmessage = function(event) {
var data = event.data;
var type = data.substring(0, data.indexOf("-"));
var msg = data.substring(data.indexOf("-") + 1);
if (type == "1") {
$("#doneMsg").html($("#doneMsg").html() + msg + "<br/>");
} else if (type == "2") {
$("#doingMsg").html(msg + "<br/>");
} else if (type == "3") {
$("#errorMsg").html(msg + "<br/>" + $("#errorMsg").html());
} else { } };
websocket.onerror = function(event) {
$(".commonMsg").each(function() {
$(this).html($(this).html() + "websocket发生错误<br/>")
});
};
websocket.onclose = function(event) {
$(".commonMsg").each(function() {
$(this).html($(this).html() + "已关闭<br/>")
});
};
});
</script>

6.后端使用

        //websocket发给前端
Iterator<Entry<String, WebSocketSession>> it = MyWebSocketHandler.userSocketSessionMap.entrySet().iterator();
// 发给同一userId的客户端
while (it.hasNext()) { final Entry<String, WebSocketSession> entry = it.next();
String keyUserId = entry.getKey().substring(entry.getKey().indexOf("-") + 1);
WebSocketSession session = entry.getValue();
if (session.isOpen() && keyUserId.equals(userId)) {
try {
if (session.isOpen()) {
synchronized(session) {
entry.getValue().sendMessage(new TextMessage(msg));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

  注意:当多线程发送消息时,同一个WebSocketSession一次只能发送条消息,所以需要用synchronize将session锁住

HTML5通讯协议——WebSocket的更多相关文章

  1. websocket通讯协议(10版本)简介

    前言: 工作中用到了websocket 协议10版本的,英文的协议请看这里: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotoc ...

  2. WebSocke实时通讯协议

    WebSocket 是什么? WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议 ...

  3. 带你认识HTML5中的WebSocket

    这篇文章主要介绍了带你认识HTML5中的WebSocket,本文讲解了HTML5 中的 WebSocket API 是个什么东东.HTML5 中的 WebSocket API 的用法.带Socket. ...

  4. HTML5新特性 websocket(重点)--多对多聊天室

    一.html5新特性  websocket(重点)--多对多聊天室 HTTP:超文本传输协议 HTTP作用:传输网页中资源(html;css;js;image;video;..) HTTP是浏览器搬运 ...

  5. 基于dubbo框架下的RPC通讯协议性能测试

    一.前言 Dubbo RPC服务框架支持丰富的传输协议.序列化方式等通讯相关的配置和扩展.dubbo执行一次RPC请求的过程大致如下:消费者(Consumer)向注册中心(Registry)执行RPC ...

  6. MODBUS-RTU通讯协议简介

    MODBUS-RTU通讯协议简介   什么是MODBUS? MODBUS 是MODICON公司最先倡导的一种软的通讯规约,经过大多数公司 的实际应用,逐渐被认可,成为一种标准的通讯规约,只要按照这种规 ...

  7. 【读书笔记】iOS-防止通讯协议被轻易破解的方法

    开发者可以选择类似Protobuf之类的二进制通讯协议或者自己实现通讯协议,对于传输的内容进行一定程度的加密,以增加黑客破解协议的难度. 参考资料: <iOS开发进阶> --唐巧

  8. CNN 美国有线电视新闻网 wapCNN WAP 指无线应用通讯协议 ---- 美国有线电视新闻网 的无线应用

    wapCNN  wap指无线应用通讯协议  CNN美国有线电视新闻网   固, wapCNN 美国有线电视新闻网的无线应用 -------------------------------------- ...

  9. Netty 对通讯协议结构设计的启发和总结

    Netty 通讯协议结构设计的总结 key words: 通信,协议,结构设计,netty,解码器,LengthFieldBasedFrameDecoder 原创 包含与机器/设备的通讯协议结构的设计 ...

随机推荐

  1. Helm包管理工具(简介、安装、方法)

    认识Helm 每次我们要部署一个应用都需要写一个配置清单(维护一套yaml文件),但是每个环境又不一样.部署一套新的环境成本是真的很高.如果我们能够使用类似于yum的工具来安装我们的应用的话那就太好了 ...

  2. react项目后台及上线步骤

    应同学要求,本人将react项目创建后台及上线流程书写如下: 前端部分 略…… 后台部分 (注:这里的后台是用的nodejs搭建的,使用的是express框架+ejs模板) 首先通过express快速 ...

  3. Ext.Net的一例Ext Undefined解决办法

    在运行的产品里发现了一例Ext Undefined报错.经过仔细排查原因是一个Ext.net按钮控件前端显示部分使用了<% if()  <%> 动态控制输出Html脚本(有对应的后端 ...

  4. Selenium-Switch--切换浏览器tab/iframe/alart

    Switch 我们在UI自动化测试时,总会出现新建一个tab页面.弹出一个浏览器级别的弹框或者是出现一个iframe标签,这时我们用WebDriver提供的Api接口就无法处理这些情况了.需要用到Se ...

  5. 关于微信emoji 表情数据库存不了,或者显示为???的问题

    必须我utf8mb4,数据库就可以存 2. 数据库连接也需要是utf8mb4

  6. 软件测试-Svn服务器搭建全过程-基于Centos6.7-64bit

    本文详细介绍了在CentOs6.7-64bit服务器上搭建SVN版本控制服务 工具准备 CentOs6.7-64bit操作系统:关闭linux防火墙:设置定固IP--DHCP(动态):安装系统过程中开 ...

  7. Python自动化中的鼠标事件

    1)form selenium.webdriver.common.action_chains import ActionChains  导入该模块 2)ActionChains(driver) :用于 ...

  8. SpringMVC整合Thymeleaf3

    (1).pom添加相关依赖 <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thym ...

  9. I/O多路复用之select、poll、epoll

    很早之前有写过篇IO多路复用的文章:https://www.cnblogs.com/klcf0220/archive/2013/05/14/3077003.html 参考链接:https://segm ...

  10. jmeter知识总结(一)

    Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件.相比Loadrunner而言,JMeter小巧轻便且免费,逐渐成为了主流的性能测试工具,是每个测试人员都必须要掌握的工 ...