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文档会有什么问题? 理想情况下,为所开发的服务编写接口文档,能提高与 ...
随机推荐
- FastAPI框架
目录 FastAPI框架 安装 基本使用 模版渲染 安装jinja2 基本使用 form表单数据交互 基本数据 文件交互 静态文件配置 FastAPI框架 该框架的速度(天然支持异步)比一般的djan ...
- AJ学IOS 之二维码学习,快速生成二维码
AJ分享,必须精品 二维码是一项项目中可能会用到的,iOS打开相机索取二维码的速度可不是Android能比的...(Android扫描二维码要来回来回晃...) 简单不多说,如何把一段资料(网址呀,字 ...
- Android 修改应用程序字体
在网上搜索了相关资料,研究了两种算是比较快速的改变程序字体的方法,好,先来介绍着两种方法. 首先第一种方法是重写控件(以Textview为例): 1.Android在写程序的时候谷歌早已将所有字体都默 ...
- SpringCloud系列之网关(Gateway)应用篇
@ 目录 前言 项目版本 网关访问 鉴权配置 限流配置 前言 由于项目采用了微服务架构,业务功能都在相应各自的模块中,每个业务模块都是以独立的项目运行着,对外提供各自的服务接口,如没有类似网关之类组件 ...
- 怎么自定义DataGridViewColumn(日期列,C#)
参考:https://msdn.microsoft.com/en-us/library/7tas5c80.aspx 未解决的问题:如果日期要设置为null,怎么办? DataGridView控件提供了 ...
- 杭电1080 J - Human Gene Functions
题目大意: 两个字符串,可以再中间任何插入空格,然后让这两个串匹配,字符与字符之间的匹配有各自的分数,求最大分数 最长公共子序列模型. dp[i][j]表示当考虑吧串1的第i个字符和串2的第j个字符时 ...
- Coin Change UVA
Suppose there are 5 types of coins: 50-cent, 25-cent, 10-cent, 5-cent, and 1-cent. We want to makech ...
- 一口气带你踩完五个 List 的大坑,真的是处处坑啊!
List 可谓是我们经常使用的集合类之一,几乎所有业务代码都离不开 List.既然天天在用,那就没准就会踩中这几个 List 常见坑. 今天我们就来总结这些常见的坑在哪里,捞自己一手,防止后续同学再继 ...
- HTTPie:替代 Curl 和 Wget 的现代 HTTP 命令行客户端
HTTPie 工具是现代的 HTTP 命令行客户端,它能通过命令行界面与 Web 服务进行交互. -- Magesh Maruthamuthu 大多数时间我们会使用 curl 命令或是 wget 命令 ...
- python中文资源大全
Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-python 是 vinta 发起维护的 Python 资源列 ...