Spring WebSocket 支持

通常应用程序之间交换信息会使用如 JMS、AMQP 等技术,但是它们都无法实现浏览器客户端和服务器之间的全双工通信,基于 HTML5 的 WebSocket 协议可以用于实现浏览器和服务器之间的全双工通信;
相对于传统的服务器轮询方式,WebSocket 可以为长连接的建立一个低延迟、全双工、跨域的通信通道,这样的方式更加高效便捷,很适合需要实时通信的场景;
目前浏览器对于 WebSocket 的支持情况如下:
  • IE:10.0(完整支持);
  • FireFox:4.0(部分支持),6.0(完整支持);
  • Chrome:4.0(部分支持),13.0(完整支持);
  • Opera:11.0(部分支持),12.10(完整支持);
  • Safari:5.0(部分支持),12.10(完整支持);
  • IOS Safari:4.2(部分支持),6.0(完整支持);
  • Android Browser:4.4(完整支持);
目前部分服务端对于 WebSocket 的支持情况如下:
  • JavaEE 7.0+
  • Tomcat 8.0+
  • Jetty 7.0+
WebSocket 通信的 URL 是以 “ws://” 或 “wss://” 开头的,分别对应 “http://”,“https://”;
Spring 从 4.0 开始全面支持 WebSocket ,该支持包括以下几个方面:
  • 发送和接收信息的 API;
  • 用于发送信息的模板;
  • 支持 SockJS(用于解决浏览器、服务器及代理不支持 WebSocket 的问题);
在 Spring 中使用 WebSocket 需要导入以下依赖包:
org.springframework:spring-web
org.springframework:spring-webmvc
org.springframework:spring-websocket

以下完整示例代码地址:
https://gitee.com/assad/springframework-test-mvc-websocket

Spring MVC WebSocket 程序的实现

Spring MVC 提供了 WebSocketHandler 用于支持 WebSocket 的收发信息API,同时提供一个实现类AbstractWebSocketHandler ,可以继承该类方便地实现一个 WebSocket 服务端控制器,该接口常用地方法如下:
handleTextMessage 处理接收的文本类型消息
handleBinaryMessage 处理接收的二进制类型消息
handlePongMessage 处理接收的Pong类型的消息
handleTransportError 处理接收Exception信息
afterConnectionEstablished 在建立 Websocket 连接后的执行方法
afterConnectionClosed 在关闭 Websocket 连接后的执行方法
示例代码模块(代码地址见上面):
site.assad.web.HelloWebScoketHandler(websocket服务端控制器)
resources/applicationContext.xml(配置文件)
webapp/hello.jsp(websocket客户端)
一个示例的服务端控制器 HelloWebSocketHandler 如下:
 
package site.assad.web;

public class HelloWebSocketHandler extends AbstractWebSocketHandler {

    @Override

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

        //处理文本消息

        System.out.println("get message: " + message.getPayload());

        //模拟延时

        Thread.sleep(2000);

        //发送信息

        System.out.println("send message: Hello world!");

        session.sendMessage(new TextMessage("from server: Hello world!"));

    }

    @Override

    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

        System.out.println("websocket connected");

    }

    @Override

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

        System.out.println("websocket connection close");

    }

}

在 spring 上线文配置文件 applicationContext.xml 中装载该 WebSocketHandler:
 
    <!--装载 WebSocketHandler bean -->

    <bean id="helloHandler" class="site.assad.web.HelloWebSocketHandler" />

    <!--将 WebSocketHandler 映射到对应路由-->

    <webscket:handlers>

        <webscket:mapping  handler="helloHandler" path="/hello"/>>

    </webscket:handlers>

客户端 hello.jsp 如下:
 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

<head>

    <title>websocket 测试</title>

    <script type="text/javascript">

        //创建 websocket

        var url = 'ws://'+ window.location.host + '<%= request.getContextPath() %>/hello';

        var sock = new WebSocket(url);

        //websocket 连接行为

        sock.onopen = function(){

            console.log('开启 websocket 连接');

            sayHello();

        };

        //websocket 接受到信息行为

        sock.onmessage = function(e){

            console.log('接受信息',e.data);

            setTimeout(function(){sayHello()},2000);

        };

        //websocket 关闭行为

        sock.onclose = function(){

            console.log('关闭 websocket 连接');

        };

        function sayHello() {

            console.log('发送信息:hello world!');

            sock.send('form client: Hello world!');

        }

    </script>

</head>

<body>

    Hello world!

</body>

</html>

演示程序运行的过程如下:
启动后端程序,此时服务端建立一个websocket服务端,通过浏览器访问 hello.jsp ,此时客户端建立一websocket客户端,并向服务端发送文本信息 “form client: Hello world!”,服务端接收该信息,再向客户端发送文本信息 “from server: Hello world!” ,客户端接收信息后再次向服务端发送文本信息 “form client: Hello world!”,以此循环,直到任意端断开 websocket 连接;

一个示例的具体使用场景

应用 Websocket 这样的特性,我们可以假象这么一个实际场景,有一个实时刷新某个城市PM2.5值的业务,前端输入某个城市,后端获取该程序后,不断地向前端发送该城市PM2.5的最新实时数据,并由前端实时渲染,这样的场景可以用AJAX来实现,但是使用 WebSocket 实现的效率会更高;
示例代码模块(代码地址见上面):
site.assad.service.PMService(模拟PM2.5值数据获取的业务层)
site.assad.web.PMWebScoketHandler(websocket服务端控制器)
webapp/pm25.jsp(websocket客户端)
编写服务端WebSocke控制器:PMWebScoketHandler
 
package site.assad.web;

public class PMWebSocketHandler extends AbstractWebSocketHandler{

    private static final Logger log = LogManager.getLogger();

    @Autowired

    private PMService pmService;

    private MessageSendThread thread ;  //信息发送线程

    @Override

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

        String city = message.getPayload().trim();

        log.debug("get: " + city);

        if(thread == null){

            thread = new MessageSendThread(session,city);

            thread.start();

        }

        thread.setCity(city);

    }

    @Override

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

        if(thread != null)

            thread.kill();

    }

    private class MessageSendThread extends Thread{

        private volatile boolean isRunning = true;

        private WebSocketSession session ;

        private volatile String city;

        public MessageSendThread(WebSocketSession session, String city) {

            this.session = session;

            this.city = city;

        }

        public void setCity(String city) {

            this.city = city;

        }

        @Override

        public void run() {

            while(isRunning){

                try {

                    String sendMsg = pmService.getData(city);

                    log.debug("send:" + sendMsg);

                    session.sendMessage(new TextMessage(sendMsg));

                    Thread.sleep(1000);

                } catch (IOException e) {

                    e.printStackTrace();

                } catch (InterruptedException e) {

                }

            }

        }

        public void kill(){

            isRunning = false;

        }

    }

}

spring上下文装载wesocket控制器:applicationContext.xml
 
    <!--装载业务层 bean -->

    <context:component-scan base-package="site.assad.service" />

    <!--装载 WebSocketHandler bean -->

    <bean id="pmHandler" class="site.assad.web.PMWebSocketHandler" />

    <!--将 WebSocketHandler 映射到对应路由-->

    <webscket:handlers>

        <webscket:mapping  handler="pmHandler" path="/pm25"/>

    </webscket:handlers>

编写 websocket 客户端,pm25.jsp
 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

    <title>WebSocket 测试</title>

    <script type="text/javascript">

        var url = 'ws://' + window.location.host + '<%= request.getContextPath() %>/pm25'; //本机测试,真实常见下更换为服务主机 url

        var sock = new WebSocket(url);

        sock.onopen = function(){

            changeCity("bj");

        };

        sock.onmessage = function(e){

            console.log("get:"+ e.data);

            document.getElementById("showData").innerHTML = e.data;

        };

        function changeCity(city){

            console.log("send: "+city);

            sock.send(city);

        }

    </script>

</head>

<body>

    <h1>PM 2.5 AQI 实时刷新数据</h1>

    <button onclick="changeCity('bj')">北京</button>

    <button onclick="changeCity('gz')">广州</button>

    <br/>

    <p id="showData"></p>

</body>

</html>

启动服务端后,在浏览器通过 “http://127.0.0.1/<projectName>/pm25.jsp” 进行实验;

Spring MVC(11):通过 WebSocket 实现前后端全双工通信相关推荐

  1. springboot websocket_SpringBoot 集成 WebSocket 实现前后端消息互传

    WebSocket 协议是基于 TCP 的一种新的网络协议.它实现了浏览器与服务器全双工 (full-duplex) 通信-允许服务器主动发送信息给客户端. 为什么需要WebSocket? 大家都知道 ...

  2. 如何使用websocket实现前后端通信

    如何使用websocket实现前后端通信 websocket通信是很好玩的,也很有用的的通信方式,使用方式如下: 第一步由于springboot很好地集成了websocket,所以先在在pom.xml ...

  3. aes 加密_结合RSA与AES实现前后端加密通信

    结合RSA与AES实现前后端加密通信 一.思路 使用RSA秘钥生成工具生成一对公钥(A)和私钥(B),前端保留A,后端保留B. 前端发送数据时,先生成一串随机16位字符串作为AES的秘钥(C),然后使 ...

  4. 超实用,Spring Security+JWT+Vue实现一个前后端分离无状态认证Demo

    作者: 陕西颜值扛把子 https://zhuanlan.zhihu.com/p/95560389 精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 ...

  5. SpringBoot+Vue整合WebSocket实现前后端消息推送

    场景 WebSocket HTTP 协议是一种无状态的.无连接的.单向的应用层协议.它采用了请求/响应模型.通信请求只能由客户端发起,服务端对请求做出应答处理. 这种通信模型有一个弊端:HTTP 协议 ...

  6. WebSocket 实现前后端通信的笔记

    之前在做站内信时,用到了 WebSocket ,整理了一些笔记分享如下. 本文基于 SpringBoot 2.1.5,本文不涉及环境搭建. 引入依赖 在 Spring 中要使用 WebSocket 功 ...

  7. Spring Boot与JWT整合实现前后端分离的用户认证

    前言 本篇使用java-jwt作为JWT库,与Spring Boot整合实现前后端分离架构中用户认证. Spring Boot项目搭建参考: [Spring Boot系列]1. 项目搭建之一 关于JW ...

  8. websocket php apache,PHP第一篇:PHP WebSocket实现前后端数据交互,亲测可用(windows+ apache2.4 +php5.6 )...

    首先贴上参考的教程: ①:https://blog.csdn.net/lian772882/article/details/81386115(主) ②:https://www.cnblogs.com/ ...

  9. springboot flask php,使用Vue,Spring Boot,Flask,Django 完成Vue前后端分离开发(二)

    使用Vue完成前后端分离开发(二) Bravery never goes out of fashion. 勇敢永远不过时. 前面简单说了一下 Vue 项目的搭建和项目的大致页面,这里讲一下 Djang ...

最新文章

  1. pycharm中R工具包的安装
  2. 分布式系统原理 之6 两阶段提交协议
  3. 设计模式大集锦 程序员面试全攻略
  4. php curl处理get和post请求
  5. html使用element ui_Kendo UI for jQuery使用教程:自定义小部件(二)
  6. ArcGIS Flex API 中的 Flex 技术(一)--事件
  7. notepad自动对齐html代码,notepad如何存储为html格式化
  8. 【送书福利】第一次送书活动(总共10本)
  9. java学习过程记录
  10. python以文本方式字节流_如何在Python3中将文本流编码为字节流?
  11. 网络通信词汇——MCC、MNC、dbm、TAC、ECI、PCI、BAND、EARFCN、FREQ、RSSI、RSRP、RSRQ、SINR
  12. 解决“安装程序无法创建新的系统分区,也无法定位现有系统分区”问题方法
  13. 网络七层协议,五层协议概述
  14. Bug heroes虫虫英雄 超详细翻译+基本攻略
  15. python 等值面_三维等值面提取算法(Dual Contouring)
  16. 如何用GoldWave生成音频的回音效果
  17. 【过关斩将】高胜寒带你理清 “为什么从上家公司离职?”
  18. 【猿说VUE】条件渲染,绝代双骄之 v-if 和v-show
  19. Mac上一款最受欢迎的SSH客户端
  20. 高通平台wifi命令操作

热门文章

  1. 如何评估数据库的安全风险?
  2. 数据结构时间复杂度测试
  3. 2022年定制PC微信HOOK工具版本测试功能
  4. Discuz社区西瓜微信的登录插件
  5. 一个简单的贪吃蛇游戏 c
  6. Fabric安装中make release无法编译问题解决 no required module provides package
  7. 北漂的生活成本到底有多大?
  8. 软件需求工程 课堂笔记5
  9. 爱数博客备份软件 v2006 免费下载
  10. 程序员兼职平台、网站