spring对websocket的集成和使用
WebSocket是HTML5提出的一个用于通信的协议规范,该协议通过一个握手机制,在客户端和服务端之间建立一个类似于TCP的连接,从而方便客户端和服务端之间的通信。
WebSocket协议本质上是一个基于TCP的协议,是先通过HTTP/HTTPS协议发起一条特殊的HTTP请求进行握手后创建一个用于交换数据的TCP连接,此后服务端与客户端通过此TCP连接进行实时通信。客户端和服务端只需要要做一个握手的动作,在建立连接之后,服务端和客户端之间就可以通过此TCP连接进行实时通信。
websocket是建立在物理层上的连接,相比于基于网络层的长连接可以节约资源,相比于AJAX轮训可以降低服务器压力。
spring在4.0后将websocket集成进去,要使用spring的websocket的话,spring的版本要在4.0及以上。
spring使用websocket需要的jar(pom.xml)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
web.xml中对websocket的配置
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/springMVC/spring-webSocket.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
springMVC中对websocket的xml配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd"> <!-- websocket处理类 -->
<bean id="msgHandler" class="com.test.websocket.MyWebSocketHandler" />
<!-- 握手接口/拦截器 ,看项目需求是否需要-->
<bean id="handshakeInterceptor" class="com.test.websocket.MyHandshakeInterceptor" />
<websocket:handlers>
<websocket:mapping path="/websocket" handler="msgHandler" />
<websocket:handshake-interceptors>
<ref bean="handshakeInterceptor" />
</websocket:handshake-interceptors>
</websocket:handlers>
<!-- 注册 sockJS,sockJs是spring对不能使用websocket协议的客户端提供一种模拟 -->
<websocket:handlers>
<websocket:mapping path="/sockjs/websocket" handler="msgHandler" />
<websocket:handshake-interceptors>
<ref bean="handshakeInterceptor" />
</websocket:handshake-interceptors>
<websocket:sockjs />
</websocket:handlers>
</beans>
springMVC中对websocket的注解配置
@Configuration
@EnableWebSocket
public class WebSocketServerConfig implements WebSocketConfigurer { @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 添加拦截地址以及相应的websocket消息处理器
WebSocketHandlerRegistration registration = registry.addHandler(new MyWebSocketHandler(), "/websocket","sockjs/websocket");
SockJsServiceRegistration sockJS = registration.withSockJS();
// 添加拦截器
registration.addInterceptors(new MyHandshakeInterceptor());
} }
握手拦截器,继承HttpSessionHandshakeInterceptor类,做一些连接握手或者握手后的一些处理
public class MyHandshakeInterceptor extends HttpSessionHandshakeInterceptor { // 握手前
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception { System.out
.println("++++++++++++++++ HandshakeInterceptor: beforeHandshake ++++++++++++++"
+ attributes); return super.beforeHandshake(request, response, wsHandler, attributes);
} // 握手后
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) { System.out
.println("++++++++++++++++ HandshakeInterceptor: afterHandshake ++++++++++++++"); super.afterHandshake(request, response, wsHandler, ex);
}
}
创建MyWebSocketHandler类继承WebSocketHandler类(Spring提供的有AbstractWebSocketHandler类、TextWebSocketHandler类、BinaryWebSocketHandler类,看自己需要进行继承),该类主要是用来处理消息的接收和发送
public class MyWebSocketHandler implements WebSocketHandler { private Logger logger = LoggerFactory.getLogger(MsgWebSocketHandler.class); //保存用户链接
private static ConcurrentHashMap<String, WebSocketSession> users = new ConcurrentHashMap<String, WebSocketSession>();
// 连接 就绪时
@Override
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
users.put(session.getId(), session);
} // 处理信息
@Override
public void handleMessage(WebSocketSession session,
WebSocketMessage<?> message) throws Exception {
System.err.println(session + "---->" + message + ":"+ message.getPayload().toString());
} // 处理传输时异常
@Override
public void handleTransportError(WebSocketSession session,
Throwable exception) throws Exception { } // 关闭 连接时
@Override
public void afterConnectionClosed(WebSocketSession session,
CloseStatus closeStatus) {
logger.debug("用户: " + session.getRemoteAddress() + " is leaving, because:" + closeStatus); } //是否支持分包
@Override
public boolean supportsPartialMessages() {
return false;
}
}
要进行发送消息的操作,自己可以写方法,利用保存的已经完成连接的WebSocketSession,通过调用sendMessage(WebScoketMessage<?> message)方法进行消息的发送,参数message是发送的消息内容,Spring提供的类型有TextMessage、BinaryMessage、PingMessage、PongMessage。
前端客户端JS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>websocket</title>
</head>
<style type="text/css">
#div {
color: red;
}
</style>
<body>
<h1>WEBSOCKET----TEST</h1>
<div id="div"> </div>
</script>
<script type="text/javascript">
var div = document.getElementById('div');
var socket = new WebSocket('ws://127.0.0.1:8088/websocket'); socket.onopen = function(event){
console.log(event);
socket.send('websocket client connect test');
} socket.onclose = function(event){
console.log(event);
} socket.onerror = function(event){
console.log(event);
} socket.onmessage = function(event){
console.log(event)
div.innerHTML += (' @_@ ' + event.data + ' ~_~ ');
}
</script>
</body>
</html>
其实在后台也可以进行websocket客户端的创建
@Test
public void connectTest(){
WsWebSocketContainer wsWebSocketContainer = new WsWebSocketContainer();
wsWebSocketContainer.setDefaultMaxSessionIdleTimeout(300);
StandardWebSocketClient client = new StandardWebSocketClient(wsWebSocketContainer);
WebSocketHandler webSocketHandler = new MyWebSocketHandler();
String uriTemplate = "ws://127.0.0.1:8088/websocket?account=11111";
Object uriVars = null;
ListenableFuture<WebSocketSession> future = client.doHandshake(webSocketHandler, uriTemplate, uriVars);
try {
WebSocketSession session = future.get();
session.sendMessage(new TextMessage("hello world"));
} catch (InterruptedException | ExecutionException | IOException e) {
e.printStackTrace();
} } @Test
public void connectTest2(){
StandardWebSocketClient client = new StandardWebSocketClient();
WebSocketHandler webSocketHandler = new MyWebSocketHandler();
String uriTemplate = "ws://127.0.0.1:8088/websocket";
UriComponentsBuilder fromUriString = UriComponentsBuilder.fromUriString(uriTemplate);
fromUriString.queryParam("account","111111");
/*
* 作用同上,都是将请求参数填入到URI中
* MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
* params.add("account","111111");
* fromUriString.queryParams(params);
* */
URI uri = fromUriString.buildAndExpand().encode().toUri();
WebSocketHttpHeaders headers = null;
ListenableFuture<WebSocketSession> doHandshake = client.doHandshake(webSocketHandler, headers , uri);
try {
WebSocketSession session = doHandshake.get();
session.sendMessage(new TextMessage("hello world"));
} catch (InterruptedException | ExecutionException | IOException e) {
e.printStackTrace();
} }
这是我利用Junit进行的测试,实验证明是可以完成websocket的连接。
注意:websocket在进行连接的时候是可以类似get请求一样,将参数拼接到url中。还可以自己将参数封装进URI中,利用另一个方法进行连接的握手操作。
spring对websocket的集成和使用的更多相关文章
- tomcat 7下spring 4.x mvc集成websocket以及sockjs完全参考指南
之所以sockjs会存在,说得不好听点,就是因为微软是个流氓,现在使用windows 7的系统仍然有近半,而windows 7默认自带的是ie 8,有些会自动更新到ie 9,但是大部分非IT用户其实都 ...
- tomcat 7下spring 4.x mvc集成websocket以及sockjs完全参考指南(含nginx/https支持)
之所以sockjs会存在,说得不好听点,就是因为微软是个流氓,现在使用windows 7的系统仍然有近半,而windows 7默认自带的是ie 8,有些会自动更新到ie 9,但是大部分非IT用户其实都 ...
- Spring Chapter4 WebSocket 胡乱翻译 (二)
书接上文,Spring Chapter4 WebSocket 胡乱翻译 (一) 4.4.4. 消息流 一旦暴露了STOMP端点,Spring应用程序就成为连接客户端的STOMP代理. 本节介绍服务器端 ...
- Spring Chapter4 WebSocket 胡乱翻译 (一)
4. WebSocket 包含了Servlet stack,原生WebSocket交互,通过SockJS模拟,并且通过STOMP在WebSocket之上订阅.发布消息. 4.1 简介 不扯了,看到这个 ...
- Spring+SpringMvc+Mybatis框架集成搭建教程
一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...
- NoSql存储日志数据之Spring+Logback+Hbase深度集成
NoSql存储日志数据之Spring+Logback+Hbase深度集成 关键词:nosql, spring logback, logback hbase appender 技术框架:spring-d ...
- 菜鸟学习Spring——60s学会Spring与Hibernate的集成
一.概述. Spring与Hibernate的集成在企业应用中是很常用的做法通过Spring和Hibernate的结合能提高我们代码的灵活性和开发效率,下面我就一步一步的给大家讲述Spring如何和H ...
- 玩转spring boot——websocket
前言 QQ这类即时通讯工具多数是以桌面应用的方式存在.在没有websocket出现之前,如果开发一个网页版的即时通讯应用,则需要定时刷新页面或定时调用ajax请求,这无疑会加大服务器的负载和增加了客户 ...
- spring boot / cloud (三) 集成springfox-swagger2构建在线API文档
spring boot / cloud (三) 集成springfox-swagger2构建在线API文档 前言 不能同步更新API文档会有什么问题? 理想情况下,为所开发的服务编写接口文档,能提高与 ...
随机推荐
- 初识指令重排序,Java 中的锁
本文是作者原创,版权归作者所有.若要转载,请注明出处.本文只贴我觉得比较重要的源码 指令重排序 Java语言规范JVM线程内部维持顺序化语义,即只要程序的最终结果与它顺序化情况的结果相等,那么指令的执 ...
- 用Python爬取大众点评数据,推荐火锅店里最受欢迎的食品
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:有趣的Python PS:如有需要Python学习资料的小伙伴可以加点 ...
- I NEED A OFFER! HDU - 1203
概率+0 1背包 要算成功的最大概率,那就是失败的最小概率,所以01背包直接让失败的概率最小就行了. 注意: 概率与概率之间是要相乘的,不是相加. #include<bits/stdc++.h& ...
- OkHttp 优雅封装 HttpUtils 之 气海雪山初探
曾经在代码里放荡不羁,如今在博文中日夜兼行,只为今天与你分享成果.如果觉得本文有用,记得关注我,我将带给你更多. 介绍 HttpUtils 是近期开源的对 OkHttp 轻量封装的框架,它独创的异步预 ...
- Java读源码之CountDownLatch
前言 相信大家都挺熟悉 CountDownLatch 的,顾名思义就是一个栅栏,其主要作用是多线程环境下,让多个线程在栅栏门口等待,所有线程到齐后,栅栏打开程序继续执行. 案例 用一个最简单的案例引出 ...
- 2020.4面试分享(7面收5个offer)
都说金三银四是找工作的最佳时节,由于本人的个人职业规划跟目前工作内容不太相符(具体原因就不透露了,领导平时也要来这里逛,哈哈),四月份挑选了10多家公司投递简历(公司规模从几十人到上万人都有),参加了 ...
- powershell提示无法将“”项识别
解决: 完成! 解释: 权限问题.Powershell脚本的4种执行权限介绍,Windows默认不允许任何脚本运行,我们可以使用"Set-ExecutionPolicy"cmdle ...
- df卡住的解决办法
在使用网络存储时,如果网络存储出问题.比如使用NFS,网络中断,df -h会卡住 情形一 ctrl+c是能取消中断的,这种情况算是比较幸运.使用mount查看有哪些挂载点,将其卸载即可. 情形二 ct ...
- Python最佳工程实践,建立一个完美的工程项目
在程序开发时候一套好的开发环境和工具栈,可以帮我们极大的提高开发的效率,避免把大量时间浪费在周边琐事上.本文以Python为例,教大家如何快速打造完美的Python项目开发环境:内容涵盖了模块依赖管理 ...
- TensorFlow命令行参数FLAGS使用
import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' import tensorflow as tf #tensorboard --logdir=&qu ...