SpringBoot 全家桶 | WebSocket服务端与客户端实例

本文源码:Gitee·点这里

介绍

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

参考
  1. Spring Framework 中文文档

  2. WebSocket 在线测试 v13

  3. HTML5 WebSocket

Server端

Server端我们使用SpringBoot的一个包spring-boot-starter-websocket,我们来引入它

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
WebSocket处理器

WebSocket处理器用来处理客户端发送的消息,Spring中常用的是两个TextWebSocketHandlerBinaryWebSocketHandler,我们使用TextWebSocketHandler

import org.springframework.web.socket.handler.TextWebSocketHandler;public class ChatWebSocketHandler extends TextWebSocketHandler {@Override
 public void afterConnectionEstablished(WebSocketSession session) throws Exception {

 }@Override
 protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
 String msg = message.getPayload();
 }

 @Override
 public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

 }

 @Override
 public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {

 }
}

重写TextWebSocketHandler的四个方法:

  • afterConnectionEstablished 成功创建连接后调用

  • handleTextMessage 收到客户端消息后调用

  • handleTransportError 连接异常时调用

  • afterConnectionClosed 连接关闭后调用

WebSocketSession是客户端与服务端建立的回话,可以通过close()方法主动关闭连接

TextMessage为收到的消息,可以通过getPayload()方法获取消息内容

WebSocket配置

有了处理器了,就可以将此处理器映射到指定path上了,这需要增加一些配置,Spring提供一个配置接口WebSocketConfigurer,我们来实现它,并启用@EnableWebSocket

import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {/**
 * 用于将WebSocket处理程序映射到特定URL
 *
 * @param registry
 */
 @Override
 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
 registry.addHandler(chatWebSocketHandler(), "chat") // 添加消息处理器
 .setAllowedOrigins("*"); // 设置跨域
 }

 /**
 * 自定义消息处理器
 *
 * @return
 */
 @Bean
 public ChatWebSocketHandler chatWebSocketHandler() {
 return new ChatWebSocketHandler();
 }}

重写registerWebSocketHandlers方法,通过registry.addHandler()将消息处理器添加,并指定映射的path,服务端WebSocket地址为 ws://host:port/path

注:需要注意的一点,这里要设置跨域,使用setAllowedOrigins方法即可。

至此WebSocket的服务端就可以使用了,还有一些其他骚操作继续往下看

WebSocket握手拦截器

在建立连接前,我们可以通过握手拦截器来拦截非法请求,需要实现SpringHandshakeInterceptor接口

import org.springframework.web.socket.server.HandshakeInterceptor;public class ChatHandshakeInterceptor implements HandshakeInterceptor {private final Logger log = LoggerFactory.getLogger(this.getClass());@Override
 public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
 log.info("--------------握手前拦截");
 return true;
 }@Override
 public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
 log.info("--------------完成握手");
 }
}

实现两个方法:

  • beforeHandshake握手前,该方法返回true表示继续建立连接,返回false则终止

  • afterHandshake握手后

WebSocketConfig配置文件增加

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
 registry.addHandler(chatWebSocketHandler(), "chat") // 添加消息处理器
 .addInterceptors(chatHandshakeInterceptor()) // 添加握手拦截器
 .setAllowedOrigins("*"); // 设置跨域
}
/**
 * 自定义消息拦截器
 *
 * @return
 */
@Bean
public ChatHandshakeInterceptor chatHandshakeInterceptor() {
 return new ChatHandshakeInterceptor();
}
Session空闲失效时间配置

一个会话连接后不可能一直不断开,这需要增加一些配置来约束超时时间;还可以设置消息缓冲区大小等(如果Nginx中配置了超时时间,此处可以忽略),上代码

WebSocketConfig配置文件增加

/**
 * 其他配置,如session空闲失效时间,消息缓冲区大小
 *
 * @return
 */
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
 ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
 container.setMaxTextMessageBufferSize(8192);
 container.setMaxSessionIdleTimeout(10 * 60 * 1000L);
 return container;
}
Nginx配置

大部分服务器都使用了Nginx代理,那么需要增加一些配置来支持WS协议

# 支持WS协议
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
​
# 会话超时时间
proxy_connect_timeout 620;
proxy_send_timeout 620;
proxy_read_timeout 620;
Client端

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

创建WebSocket连接

连接协议使用wspath为服务端消息处理器映射的path

var ws = new WebSocket("ws://127.0.0.1:8080/chat");
WebSocket事件与方法
if (typeof (WebSocket) == "undefined") {
    alert("您的浏览器不支持WebSocket")
    return
}

// 打开一个 web socket
var ws = new WebSocket("ws://127.0.0.1:8080/chat");

ws.onopen = function()
{
    // Web Socket 已连接上,使用 send() 方法发送数据
    ws.send("发送数据");
    alert("数据发送中...");
};

ws.onmessage = function (evt) 
{ 
    var received_msg = evt.data;
    alert("数据已接收...");
};

ws.onclose = function()
{ 
    // 关闭 websocket
    alert("连接已关闭..."); 
};

ws.onerror = function () {
    // 连接错误
    alert("连接错误..."); 
    ws.close();
}

四个监听事件

  • onopen 与服务端连接成功

  • onmessage 接收服务端发送的消息

  • onclose 连接关闭

  • onerror 连接异常

两个方法

  • send() 向服务端发送消息

  • close()关闭与服务端的连接

聊天Demo演示

本demo简单实现用户A向用户B发送消息,用户B也可以回复消息,具体内容请移步我的码云!

demo.png

完整代码

springboot-websocket

timg (2).jpg

WebSocket客户端服务端实例源码 WebSocket ws实例 HTML5 用java实现的服务端 Websocket与服务器的正常通信 众所周知,Web 应用的交互过程通常是客户端通过浏览器发出一个请求,服务器端接收请求后进行处理并返回结果给客户端客户端浏览器将信息呈现,这种机制对于信息变化不是特别频繁的应用尚可,但对于实时要求高、海量并发的应用来说显得捉襟见肘,尤其在当前业界移动互联网蓬勃发展的趋势下,高并发与用户实时响应是 Web 应用经常面临的问题,比如金融证券的实时信息,Web 导航应用中的地理位置获取,社交网络的实时消息推送等。 传统的请求-响应模式的 Web 开发在处理此类业务场景时,通常采用实时通讯方案,常见的是: 轮询,原理简单易懂,就是客户端通过一定的时间间隔以频繁请求的方式向服务器发送请求,来保持客户端和服务器端的数据同步。问题很明显,当客户端以固定频率向服务器端发送请求时,服务器端的数据可能并没有更新,带来很多无谓请求,浪费带宽,效率低下。 基于 Flash,AdobeFlash 通过自己的 Socket 实现完成数据交换,再利用 Flash 暴露出相应的接口为 JavaScript 调用,从而达到实时传输目的。此方式比轮询要高效,且因为 Flash 安装率高,应用场景比较广泛,但在移动互联网终端上 Flash 的支持并不好。IOS 系统中没有 Flash 的存在,在 Android 中虽然有 Flash 的支持,但实际的使用效果差强人意,且对移动设备的硬件配置要求较高。2012 年 Adobe 官方宣布不再支持 Android4.1+系统,宣告了 Flash 在移动终端上的死亡。 从上文可以看出,传统 Web 模式在处理高并发及实时性需求的时候,会遇到难以逾越的瓶颈,我们需要一种高效节能的双向通信机制来保证数据的实时传输。在此背景下,基于 HTML5 规范的、有 Web TCP 之称的 WebSocket 应运而生。 早期 HTML5 并没有形成业界统一的规范,各个浏览器和应用服务器厂商有着各异的类似实现,如 IBM 的 MQTT,Comet 开源框架等,直到 2014 年,HTML5 在 IBM、微软、Google 等巨头的推动和协作下终于尘埃落地,正式从草案落实为实际标准规范,各个应用服务器及浏览器厂商逐步开始统一,在 JavaEE7 中也实现了 WebSocket 协议,从而无论是客户端还是服务端WebSocket 都已完备,读者可以查阅HTML5 规范,熟悉新的 HTML 协议规范及 WebSocket 支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农StayUp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值