WebSocket 详解教程 下

简介: WebSocket 详解教程 下

在 Spring 实现 WebSocket 服务器大概分为以下几步:

创建 WebSocket 处理器

扩展 TextWebSocketHandler 或 BinaryWebSocketHandler ,你可以覆写指定的方法。Spring 在收到 WebSocket 事件时,会自动调用事件对应的方法。

import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;
public class MyHandler extends TextWebSocketHandler {
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        // ...
    }
}

WebSocketHandler 源码如下,这意味着你的处理器大概可以处理哪些 WebSocket 事件:

public interface WebSocketHandler {
   /**
    * 建立连接后触发的回调
    */
   void afterConnectionEstablished(WebSocketSession session) throws Exception;
   /**
    * 收到消息时触发的回调
    */
   void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception;
   /**
    * 传输消息出错时触发的回调
    */
   void handleTransportError(WebSocketSession session, Throwable exception) throws Exception;
   /**
    * 断开连接后触发的回调
    */
   void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception;
   /**
    * 是否处理分片消息
    */
   boolean supportsPartialMessages();
}

配置 WebSocket

配置有两种方式:注解和 xml 。其作用就是将 WebSocket 处理器添加到注册中心。

1.实现 WebSocketConfigurer

import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/myHandler");
    }
    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler();
    }
}

1.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.xsd
        http://www.springframework.org/schema/websocket
        http://www.springframework.org/schema/websocket/spring-websocket.xsd">
    <websocket:handlers>
        <websocket:mapping path="/myHandler" handler="myHandler"/>
    </websocket:handlers>
    <bean id="myHandler" class="org.springframework.samples.MyHandler"/>
</beans>

更多配置细节可以参考:Spring WebSocket 文档

javax.websocket

如果不想使用 Spring 框架的 WebSocket API,你也可以选择基本的 javax.websocket。

首先,需要引入 API jar 包。

<!-- To write basic javax.websocket against -->
<dependency>
  <groupId>javax.websocket</groupId>
  <artifactId>javax.websocket-api</artifactId>
  <version>1.0</version>
</dependency>

如果使用嵌入式 jetty,你还需要引入它的实现包:

<!-- To run javax.websocket in embedded server -->
<dependency>
  <groupId>org.eclipse.jetty.websocket</groupId>
  <artifactId>javax-websocket-server-impl</artifactId>
  <version>${jetty-version}</version>
</dependency>
<!-- To run javax.websocket client -->
<dependency>
  <groupId>org.eclipse.jetty.websocket</groupId>
  <artifactId>javax-websocket-client-impl</artifactId>
  <version>${jetty-version}</version>
</dependency>

@ServerEndpoint

这个注解用来标记一个类是 WebSocket 的处理器。

然后,你可以在这个类中使用下面的注解来表明所修饰的方法是触发事件的回调

// 收到消息触发事件
@OnMessage
public void onMessage(String message, Session session) throws IOException, InterruptedException {
    ...
}
// 打开连接触发事件
@OnOpen
public void onOpen(Session session, EndpointConfig config, @PathParam("id") String id) {
    ...
}
// 关闭连接触发事件
@OnClose
public void onClose(Session session, CloseReason closeReason) {
    ...
}
// 传输消息错误触发事件
@OnError
public void onError(Throwable error) {
    ...
}

ServerEndpointConfig.Configurator

编写完处理器,你需要扩展 ServerEndpointConfig.Configurator 类完成配置:

public class WebSocketServerConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        sec.getUserProperties().put(HttpSession.class.getName(), httpSession);
    }
}

然后就没有然后了,就是这么简单。

WebSocket 代理

如果把 WebSocket 的通信看成是电话连接,Nginx 的角色则像是电话接线员,负责将发起电话连接的电话转接到指定的客服。

Nginx 从 1.3 版开始正式支持 WebSocket 代理。如果你的 web 应用使用了代理服务器 Nginx,那么你还需要为 Nginx 做一些配置,使得它开启 WebSocket 代理功能。

以下为参考配置:

server {
  # this section is specific to the WebSockets proxying
  location /socket.io {
    proxy_pass http://app_server_wsgiapp/socket.io;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 600;
  }
}

更多配置细节可以参考:Nginx 官方的 websocket 文档

FAQ

HTTP 和 WebSocket 有什么关系?

Websocket 其实是一个新协议,跟 HTTP 协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是 HTTP 协议上的一种补充。

Html 和 HTTP 有什么关系?

Html 是超文本标记语言,是一种用于创建网页的标准标记语言。它是一种技术标准。Html5 是它的最新版本。

Http 是一种网络通信协议。其本身和 Html 没有直接关系。

完整示例

如果需要完整示例代码,可以参考我的 Github 代码:

Spring 对 WebSocket 支持的示例

嵌入式 Jetty 服务器的 WebSocket 示例

spring-websocket 和 jetty 9.3 版本似乎存在兼容性问题,Tomcat则木有问题。

我尝试了好几次,没有找到解决方案,只好使用 Jetty 官方的嵌入式示例在 Jetty 中使用 WebSocket 。

资料

知乎高票答案——WebSocket是什么原理 by Ovear

对 WebSocket 原理的阐述简单易懂。

WebSocket 教程 by ruanyf

阮一峰大神的科普一如既往的浅显易懂。

WebSockets by fullstackpython

Nginx 官方的 websocket 文档

Spring WebSocket 文档

Tomcat7 WebSocket 文档

Jetty WebSocket 文档

目录
相关文章
|
2月前
|
前端开发 网络协议
netty整合websocket(完美教程)
本文是一篇完整的Netty整合WebSocket的教程,介绍了WebSocket的基本概念、使用Netty构建WebSocket服务器的步骤和代码示例,以及如何创建前端WebSocket客户端进行通信的示例。
284 2
netty整合websocket(完美教程)
|
2月前
|
网络协议 前端开发 JavaScript
WebSocket 教程汇总指南,从入门到熟练
本文将带你从零开始,逐步掌握 WebSocket 的基本概念、实现方法和应用场景,通过一系列详细的教程和实践案例,帮助你从入门到熟练地使用 WebSocket 技术。无论你是初学者还是有一定经验的开发者,本文都能为你提供有价值的信息和指导。
|
5月前
|
XML JSON Go
Swoole与Go系列教程之WebSocket服务的应用
在 WebSocket 协议出现之前,Web 应用为了能过获取到实时的数据都是通过不断轮询服务端的接口。轮询的效率、延时很低,并且很耗费资源。
1059 2
Swoole与Go系列教程之WebSocket服务的应用
|
5月前
|
网络协议 前端开发 JavaScript
WebSocket 【实用教程】
WebSocket 【实用教程】
109 1
|
6月前
|
JavaScript 前端开发 Java
蓝易云 - Java现实WebSocket教程
以上就是在Java中实现WebSocket的基本步骤。
31 1
|
前端开发 Java Maven
springboot整合websocket最基础入门使用教程详解
springboot整合websocket最基础入门使用教程详解
3551 0
springboot整合websocket最基础入门使用教程详解
|
移动开发 JavaScript 前端开发
WebSocket 详解教程 上
WebSocket 详解教程 上
525 0
WebSocket 详解教程    上
|
消息中间件 JSON JavaScript
Springboot 整合Websocket+Stomp协议+RabbitMQ做消息代理 实例教程
Springboot 整合Websocket+Stomp协议+RabbitMQ做消息代理 实例教程
1891 0
Springboot 整合Websocket+Stomp协议+RabbitMQ做消息代理 实例教程
|
XML 前端开发 JavaScript
SpringBoot如何整合WebSocket? | 带你读《SpringBoot实战教程》之四十一
WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。
SpringBoot如何整合WebSocket? | 带你读《SpringBoot实战教程》之四十一
|
JSON 前端开发 小程序
Websocket直播间聊天室教程 - GoEasy快速实现聊天室
近期线上直播非常的火爆,很多朋友问如何用GoEasy实现直播间聊天室,然后我们就推出了这一篇直播间教程,希望能够为有直播间聊天室开发需求的开发者提供参考思路。
Websocket直播间聊天室教程 - GoEasy快速实现聊天室