Spring消息之WebSocket

简介: 一、WebSocket简介     WebSocket 的定义?WebSocket是HTML5下一种全双工通信协议。在建立连接后,WebSocket服务器端和客户端都能主动的向对方发送和接收数据,就像Socket一样。

一、WebSocket简介

    WebSocket 的定义?WebSocket是HTML5下一种全双工通信协议。在建立连接后,WebSocket服务器端和客户端都能主动的向对方发送和接收数据,就像Socket一样。

    WebSocket 的由来?众所周知,HTTP协议有“无连接”、“不可靠”、“尽最大努力”的特点。WebSocket的出现可以看成是HTTP协议为了支持长连接所打的一个大补丁。首先,由 IETF 制定发布了WebSocket 协议。后来,HTML5为了在Web端支持WebSocket协议,由W3C 发布了一整套WebSocket API。其次,WebSocket主要用于Web端,对于非Web部分的意义不大(毕竟直接使用TCP就好了)。因此,在广义上,Websocket 也常常被人称为是HTML5 下的通信协议。

    HTTP 和 WebSocket 的区别?

1、HTTP 和 WebSocket 是两种不同的协议,但是HTTP负责了建立WebSocket的连接。

2、HTTP 请求以 http:// 或 https:// 开始,WebSocket 请求一般以ws:// 或 wss:// 开始。

3、所有浏览器都支持 HTTP 协议,WebScoket 可以会遇到不支持的浏览器(可通过SockJS解决)

4、HTTP长连接中,每次数据交换除了真正的数据部分外,服务器和客户端还要大量交换HTTP header,信息交换效率很低。Websocket协议通过第一个request建立了TCP连接之后,之后交换的数据都不需要发送 HTTP header就能交换数据。

    可以看看知乎上的这个回答,解释的挺生动的:https://www.zhihu.com/question/20215561

二、使用Spring的低层级WebSocket API

    先来看看客户端如何建立起WebSocket 的连接。首先,我们使用 new WebSocket(url) 创建一个WebSocket 的实例对象;然后,使用这个实例对象建立WebSocket的事件处理功能,onopen、onmessage、onclose 和 onerror 事件,分别对应着 打开连接、接收消息、关闭连接 和 异常处理 事件。

/*WebSocket*/
var url = 'ws://localhost:8080/marco2';
var sock = new WebSocket(url);


sock.onopen = function (ev) {
    console.log("正在建立连接...");
    sayMarco();
};

sock.onmessage = function (ev) {
    console.log("接收并处理消息:" + ev.data);
    if (count == 10) {
        sock.close();
    }
    setTimeout(
        function () {
            sayMarco();
            count++;
        }, 2000);
};

sock.onclose = function (ev) {
    console.log("连接关闭...");
};

sock.error = function (ev) {
    console.log("连接异常");
};

function sayMarco() {
    console.log('Sending Marco !');
    sock.send("Marco!")
}
WebSocket客户端

    接下来看看服务端这边如何建立起WebSocket的服务:

1、pom 依赖

    <!--WebSocket-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-websocket</artifactId>
      <version>4.3.13.RELEASE</version>
    </dependency>
    <!--辅助包-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.8.10</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.8.10</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.8.10</version>
    </dependency>
View Code

2、WebSocket 服务

    有两种方案可以建立起WebSocket服务,一种是基于Spring 的 spring-websocket,一种是基于 java 的 websocket-api。

  • spring-websocket

    WebSocketHandler 接口定义了服务端处理WebSocket消息要做的一系列事情。相比直接实现WebSocketHandler,更为简单的方法是扩展AbstractWebSocketHandler,这是WebSocketHandler的一个抽象实现。当然根据处理消息的类型,还可以选择继承TextWebSocketHandler(文本类消息)、BinaryWebSocketHandler(二进制消息)等...

public class MarcoHandler_2 extends AbstractWebSocketHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(MarcoHandler_2.class);

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        LOGGER.info("WebSocket 连接建立......");
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

        LOGGER.info("接收到消息:" + message.getPayload());
        Thread.sleep(2000);
        //发送文本消息
        session.sendMessage(new TextMessage("Polo!"));

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus){
        LOGGER.info("WebSocket 连接关闭......");
    }

}
View Code
  • websocket-api

    websocket-api 提供了一种基于注解、更为简单明了的方式处理WebSocket消息。美中不足的是它需要依赖 javax.websocket-api.jar。

pom依赖

    <dependency>
      <groupId>javax.websocket</groupId>
      <artifactId>javax.websocket-api</artifactId>
      <version>1.1</version>
      <scope>provided</scope>
    </dependency>
View Code

WebSocket服务

/**
 * Created by XiuYin.Cui on 2018/5/2.
 *
 * 基于注解方式的WebSocket 控制器
 */

@ServerEndpoint("/ws")
public class WsController {

    private static final Logger LOGGER = LoggerFactory.getLogger(WsController.class);

    @OnOpen
    public void onOpen(){
        LOGGER.info("连接建立");
    }

    @OnClose
    public void onClose(){
        LOGGER.info("连接关闭");
    }

    @OnMessage
    public void onMessage(String message, Session session){
        try {
            LOGGER.info("接收到消息:" + message);
            Thread.sleep(2000);
            session.getBasicRemote().sendText("polo"); //发送消息
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @OnError
    public void onError(Session session, Throwable throwable){
        throw new IllegalArgumentException(throwable);
    }


}
View Code

3、建立映射

    现在,已经有了消息处理器类,我们必须要对其进行配置,这样Spring才能将消息转发给它。在Spring的Java配置中,这需要在一个配置类上使用@EnableWebSocket,并实现WebSocketConfigurer接口。

    像所有HTTP请求一样,我们需要将WebSocket服务暴露成一个供客户端访问的url 地址。依旧有两种方式,配置类方式 和 XML方式:

3.1、配置类方式
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    /**
     *
     * @param registry 该对象可以调用addHandler()来注册信息处理器。
     */
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
          registry.addHandler(marcoHandler_2(),"/marco2")
                  .addInterceptors(webSocketHandshakeInterceptor()) //声明拦截器
                  .setAllowedOrigins("*"); //声明允许访问的主机列表
    }


    @Bean
    public MarcoHandler_2 marcoHandler_2(){
        return new MarcoHandler_2();
    }

    @Bean
    public WebSocketHandshakeInterceptor webSocketHandshakeInterceptor(){
        return new WebSocketHandshakeInterceptor();
    }
}
View Code
3.2、xml 方式
    <websocket:handlers>
        <websocket:mapping handler="marcoHandler_1" path="/marco1"/>
    </websocket:handlers>
View Code

三、使用SockJS支持WebSocket 

    既然已经有了WebSocket API 为什么还要有SockJS呢?

1、WebSocket 是一个较新的协议规范,在Web浏览器和应用服务器上可能没有得到一致的支持。

2、防火墙代理通常会限制所有除HTTP以外的流量。它们可能不支持或者还没有配置允许进行WebSocket 通信。

    SockJS 又是什么呢?

    SockJS是WebSocket技术的一种模拟,在表面上,它尽可能对应WebSocket API,但是在底层它非常智能。SockJS会优先选用WebSocket,但是如果WebSocket不可用的话,它将会从如下的方案中挑选最优的可行方案:

  • XHR流。
  • XDR流。
  • iFrame事件源。
  • iFrame HTML文件。
  • XHR轮询。
  • XDR轮询。
  • iFrame XHR轮询。
  • JSONP轮询。

    接下来让我们看看SockJS 的使用和WebSocket 有什么差异?

  • 客户端
1、SockJS客户端库

要在客户端使用SockJS,需要确保加载了SockJS客户端库。

            <script type="text/javascript" src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.js"></script>
2、修改URL,构建SockJS实例

SockJS所处理的URL是“http://”或“https://”模式,而不是“ws://”和“wss://”。

            var url = 'http://localhost:8080/marcoSockJS';
            var sock = new SockJS(url);
  • 服务端

    服务端这边只要在建立映射的时候加上SockJS的支持即可:

1、配置类方式
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    /**
     *
     * @param registry 该对象可以调用addHandler()来注册信息处理器。
     */
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
          //声明启用SockJS连接,如果前端还用 new WebSocket(url); 会报:Error during WebSocket handshake: Unexpected response code: 200
          registry.addHandler(marcoHandler_2(), "/marcoSockJS")
                  .setAllowedOrigins("*") ////声明允许访问的主机列表
                  .withSockJS();
    }


    @Bean
    public MarcoHandler_2 marcoHandler_2(){
        return new MarcoHandler_2();
    }
    
}
View Code
2、XML方式
    <websocket:handlers>
        <websocket:mapping handler="marcoHandler_1" path="/marco1"/>
        <websocket:sockjs/> <!--声明启用SockJS功能-->
    </websocket:handlers>
View Code

 

 

效果展示:

演示源码下载链接:https://github.com/JMCuixy/SpringWebSocket/tree/developer

目录
相关文章
|
6月前
|
设计模式 Java Spring
【Spring源码】WebSocket做推送动作的底层实例是谁
我们都知道WebSocket可以主动推送消息给用户,那做推送动作的底层实例究竟是谁?我们先整体看下整个模块的组织机构。可以看到handleMessage方法定义了每个消息格式采用不同的消息处理方法,而这些方法该类并**没有实现**,而是留给了子类去实现。
【Spring源码】WebSocket做推送动作的底层实例是谁
|
4月前
|
前端开发 网络协议 JavaScript
在Spring Boot中实现基于WebSocket的实时通信
在Spring Boot中实现基于WebSocket的实时通信
|
25天前
|
开发框架 前端开发 网络协议
Spring Boot结合Netty和WebSocket,实现后台向前端实时推送信息
【10月更文挑战第18天】 在现代互联网应用中,实时通信变得越来越重要。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为客户端和服务器之间的实时数据传输提供了一种高效的解决方案。Netty作为一个高性能、事件驱动的NIO框架,它基于Java NIO实现了异步和事件驱动的网络应用程序。Spring Boot是一个基于Spring框架的微服务开发框架,它提供了许多开箱即用的功能和简化配置的机制。本文将详细介绍如何使用Spring Boot集成Netty和WebSocket,实现后台向前端推送信息的功能。
250 1
|
30天前
|
前端开发 Java C++
RSocket vs WebSocket:Spring Boot 3.3 中的两大实时通信利器
本文介绍了在 Spring Boot 3.3 中使用 RSocket 和 WebSocket 实现实时通信的方法。RSocket 是一种高效的网络通信协议,支持多种通信模式,适用于微服务和流式数据传输。WebSocket 则是一种标准协议,支持全双工通信,适合实时数据更新场景。文章通过一个完整的示例,展示了如何配置项目、实现前后端交互和消息传递,并提供了详细的代码示例。通过这些技术,可以大幅提升系统的响应速度和处理效率。
|
2月前
|
JavaScript 前端开发 Java
【颠覆传统】Spring框架如何用WebSocket技术重塑实时通信格局?揭秘背后的故事与技术细节!
【9月更文挑战第4天】随着Web应用对实时交互需求的增长,传统的HTTP模型已无法满足现代应用的要求,特别是在需要持续、双向通信的场景下。WebSocket协议由此诞生,提供全双工通信渠道,使服务器与客户端能实时互发消息。作为Java开发中最受欢迎的框架之一,Spring通过其WebSocket模块支持这一协议,简化了WebSocket在Spring应用中的集成。
55 0
|
3月前
|
JavaScript 前端开发 网络协议
WebSocket在Java Spring Boot+Vue框架中实现消息推送功能
在现代Web应用中,实时消息提醒是一项非常重要的功能,能够极大地提升用户体验。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为实现实时消息提醒提供了高效且低延迟的解决方案。本文将详细介绍如何在Java Spring Boot后端和Vue前端框架中利用WebSocket实现消息提醒功能。
158 0
|
5月前
|
前端开发 JavaScript 安全
集成WebSocket在Spring Boot中可以用于实现实时的双向通信
集成WebSocket在Spring Boot中可以用于实现实时的双向通信
86 4
|
4月前
|
监控 网络协议 Java
如何在Spring Boot中使用WebSocket
如何在Spring Boot中使用WebSocket
|
4月前
|
监控 前端开发 网络协议
如何使用Spring Boot实现WebSocket通信
如何使用Spring Boot实现WebSocket通信
|
6月前
|
网络协议 前端开发 Java
Websocket (帧格式, 握手过程, Spring 中使用 WebScoket 协议)
Websocket (帧格式, 握手过程, Spring 中使用 WebScoket 协议)
67 4