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的集成和使用的更多相关文章

  1. tomcat 7下spring 4.x mvc集成websocket以及sockjs完全参考指南

    之所以sockjs会存在,说得不好听点,就是因为微软是个流氓,现在使用windows 7的系统仍然有近半,而windows 7默认自带的是ie 8,有些会自动更新到ie 9,但是大部分非IT用户其实都 ...

  2. tomcat 7下spring 4.x mvc集成websocket以及sockjs完全参考指南(含nginx/https支持)

    之所以sockjs会存在,说得不好听点,就是因为微软是个流氓,现在使用windows 7的系统仍然有近半,而windows 7默认自带的是ie 8,有些会自动更新到ie 9,但是大部分非IT用户其实都 ...

  3. Spring Chapter4 WebSocket 胡乱翻译 (二)

    书接上文,Spring Chapter4 WebSocket 胡乱翻译 (一) 4.4.4. 消息流 一旦暴露了STOMP端点,Spring应用程序就成为连接客户端的STOMP代理. 本节介绍服务器端 ...

  4. Spring Chapter4 WebSocket 胡乱翻译 (一)

    4. WebSocket 包含了Servlet stack,原生WebSocket交互,通过SockJS模拟,并且通过STOMP在WebSocket之上订阅.发布消息. 4.1 简介 不扯了,看到这个 ...

  5. Spring+SpringMvc+Mybatis框架集成搭建教程

    一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...

  6. NoSql存储日志数据之Spring+Logback+Hbase深度集成

    NoSql存储日志数据之Spring+Logback+Hbase深度集成 关键词:nosql, spring logback, logback hbase appender 技术框架:spring-d ...

  7. 菜鸟学习Spring——60s学会Spring与Hibernate的集成

    一.概述. Spring与Hibernate的集成在企业应用中是很常用的做法通过Spring和Hibernate的结合能提高我们代码的灵活性和开发效率,下面我就一步一步的给大家讲述Spring如何和H ...

  8. 玩转spring boot——websocket

    前言 QQ这类即时通讯工具多数是以桌面应用的方式存在.在没有websocket出现之前,如果开发一个网页版的即时通讯应用,则需要定时刷新页面或定时调用ajax请求,这无疑会加大服务器的负载和增加了客户 ...

  9. spring boot / cloud (三) 集成springfox-swagger2构建在线API文档

    spring boot / cloud (三) 集成springfox-swagger2构建在线API文档 前言 不能同步更新API文档会有什么问题? 理想情况下,为所开发的服务编写接口文档,能提高与 ...

随机推荐

  1. list[列表]的使用

    #!/usr/bin/env python3# -*- coding:utf-8 -*-# name:zzyushop_list = [["手机",5000], ["电脑 ...

  2. 【python实现卷积神经网络】定义训练和测试过程

    代码来源:https://github.com/eriklindernoren/ML-From-Scratch 卷积神经网络中卷积层Conv2D(带stride.padding)的具体实现:https ...

  3. 【题解】LOJ2462完美的集合(树DP 魔改Lucas)

    [题解]LOJ2462完美的集合(树DP 魔改Lucas) 省选模拟考这个??????????????????? 题目大意: 有一棵树,每个点有两个属性,一个是重量\(w_i\)一个是价值\(v_i\ ...

  4. Crowd 批量添加用户(Postman 数据驱动)

    背景 最近公司大量新员工入职,需要批量创建 Crowd 用户.设置密码.分配应用组等机械性重复工作(主要还是懒~),故把这个加餐任务分配给刚来的测试同学去研究. 一是:让他了解下 Postman 的数 ...

  5. 获取SVG中g标签的宽度高度及位置坐标

    1. 问题的出现 对于普通的HTML元素,有很多获得其宽度width.高度height.距左left.距顶top等属性的方法: 类似offsetWidth,clientWidth,width之类的,通 ...

  6. 小程序运行时如何助力传统APP转型?

    小程序和H5或者RN有什么区别?优越性在哪里? 长期以来,移动互联网界一直在寻找一种既能获得Native原生的体验,又可以低门槛快速开发的技术.在这个过程中出现了很多尝试,例如React Native ...

  7. stand up meeting 12-10

    今天项目会议正好利用了大家上课前的十五分钟,大家对项目进度和项目中所遇到的问题进行了沟通. 由于天赋同学与重阳小组沟通及时有效,在mapping的过程中直接将单词本中的type与我们单词挑战中的que ...

  8. Springboot:整合Mybaits和Druid【监控】(十一)

    MyBatis默认提供了一个数据库连接池PooledDataSource,在此我们使用阿里提供的Druid数据库连接池 项目下载:https://files.cnblogs.com/files/app ...

  9. 6、Time & Window

    一.Time & Watermark 1.1.DataStream支持的三种time DataStream有大量基于time的operator Flink支持三种time: EventTime ...

  10. php-fpm运行原理

    来源:https://blog.csdn.net/sinat_38804294/article/details/94393621 一.php-fpm由来1.cgi (common gateway in ...