当前位置: 首页 > news >正文

Spring Boot整合WebSocket介绍

为什么80%的码农都做不了架构师?>>>   hot3.png

WebSocket 简介

WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:

  • WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;
  • WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。

整合示例

本示例为演示WebSocket的广播式模式,即服务端有消息时,会将消息发送给所有连接了当前endpoint的 Browser/Client Agent

 1. maven引入依赖包

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <boot.version>1.3.6.RELEASE</boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>${boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>${boot.version}</version>
        </dependency>
    </dependencies>

2. 编写WebSocket的配置类

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
@Configuration
//开启对WebSocket的支持
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{

	/**
	 * 注册一个STOMP协议的节点,并映射到指定的URL
	 * @param registry
	 */
	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		//注册一个STOMP的endpoint,并指定使用SockJS协议
		registry.addEndpoint("/endpointSocket").withSockJS();
	}

	/**
	 * 配置消息代理
	 * @param registry
	 */
	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		//配置一个广播式的消息代理
		registry.enableSimpleBroker("/topic");
	}
}

3. 浏览器向服务器端发送消息的实体封装类

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
public class SocketMessage {
	private String message;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
}

4. 服务器向浏览器响应数据的封装实体类

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
public class SocketResponse {
	private String responseMessage;

	public SocketResponse(String responseMessage) {
		this.responseMessage = responseMessage;
	}

	public String getResponseMessage() {
		return responseMessage;
	}
}

5. 请求控制器

import com.os.china.entity.SocketMessage;
import com.os.china.entity.SocketResponse;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
@Controller
public class WebSocketController {

	private SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	//当浏览器向服务器端发送STOMP请求时,通过@MessageMapping注解来映射/getServerTime地址
	@MessageMapping(value = "/getServerTime")
	//当服务端有消息时,会对订阅了@SendTo中的路径的客户端发送消息
	@SendTo(value = "/topic/getResponse")
	public SocketResponse serverTime(SocketMessage message) throws InterruptedException {
		return new SocketResponse(message.getMessage() + sf.format(new Date()));
	}
}

6. 配置WebMvc视图映射

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
	/**
	 * MVC视图控制器配置
	 * @param registry
	 */
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		//添加一个请求映射地址为/index,返回对应视图页面为webSocket
		registry.addViewController("/index").setViewName("/webSocket");
	}
}

7. 脚本添加,将 stomp.min.js(STOMP协议的客户端脚本),socketjs.min.js(SocketJS的客户端脚本)和 jQuery脚本放在src/main/resources/static下

注:STOMP协议的客户端连接详细介绍,请移步至我的另外一篇文章,WebSocket子协议STOMP详解 https://my.oschina.net/feinik/blog/853875

8. 在项目的src/main/resources/templates下新建webSocket.html页面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>集成WebSocket示例</title>
</head>
<body>
<div>
    <button id="connect" onclick="connect();">连接</button>
    <button id="disconnect" onclick="disconnect();">断开连接</button>
    <button id="serverTimeId" onclick="getServerTime();">获取服务器端时间</button>
    <hr/>
    <span id="showServerTime"></span>
</div>
<script type="text/javascript" src="sockjs.min.js"></script>
<script type="text/javascript" src="stomp.min.js"></script>
<script type="text/javascript" src="jquery-3.1.1.min.js"></script>
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script type="text/javascript">
    var stompClient = null;
    $(function(){
        setConnect(false);
    });
    function setConnect(connected){
        $("#connect").attr({disabled:connected});
        $("#disconnect").attr({disabled:!connected});
    }
    function connect() {
        var socket = new SockJS('/endpointSocket');
        //创建STOMP客户端连接,目标地址为/endpointSocket的STOMP代理
        stompClient = Stomp.over(socket);
        //打印stomp输出信息
        stompClient.debug = function(str) {
            console.log(str + "\n");
        };
        //建立连接
        stompClient.connect({},function(frame) {
            setConnect(true);
            //连接成功后订阅/topic/getResponse目标发送的消息,该地址在Controller中用@SendTo指定
            stompClient.subscribe('/topic/getResponse', function(response) {
                showResponse(JSON.parse(response.body).responseMessage);
            });
        });
    }

    function disconnect() {
        if(stompClient != null) {
            stompClient.disconnect();
        }
        setConnect(false);
    }
    function getServerTime() {
        var message = "The server time is : ";
        //发送消息到服务端,/getServerTime地址是由Controller中的@MessageMapping指定
        stompClient.send("/getServerTime",{},JSON.stringify({'message':message}));
    }

    function showResponse(message){
        var response = $("#showServerTime");
        response.html(message);
    }

</script>
</body>
</html>

9. 编写SpringBoot的启动类

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author ZhangPengFei
 * @Discription
 * @Data 2017-3-7
 * @Version 1.0.0
 */
@SpringBootApplication
public class ApplicationTest {

	public static void main(String[] args) {
		SpringApplication application = new SpringApplication(ApplicationTest.class);
		application.setBannerMode(Banner.Mode.OFF);
		application.run(args);
	}
}

10. 启动并测试,也可打开多个浏览器窗口连接到WebSocket服务端,在其中一个浏览器窗口中点击获取服务器时间,其他两个也将接收到消息

224825_rMVf_2842105.png

好了,整合到此完结,具体代码已上传至GitHub https://github.com/AIFEINIK/SpringBoot-Learn/tree/master/spring-boot-websocket

转载于:https://my.oschina.net/feinik/blog/854880

相关文章:

  • [技术选型] Node.js
  • Spring cloud子项目
  • oracle 11gR2 ASM添加和删除磁盘
  • x-editable java 后台怎么写
  • java----数据结构与算法----集合元素的遍历:迭代器--------JavaAPI:java.util.Iterator+java.util.ListIterator...
  • Leetcode 423. Reconstruct Original Digits from English
  • JAVA加密类的使用
  • javascript数组去重复
  • Java中Collections的frequency方法
  • ng之ng-app指令
  • 使用命令wsimport构建WebService客户端
  • 【14点正式开始】技术与架构,解析如何将大数据最快落地到实践
  • Apache2.2和Apache2.4中httpd.conf配置文件 权限的异同
  • 分布式事务:不过是在一致性、吞吐量和复杂度之间,做一个选择
  • flask, SQLAlchemy, sqlite3 实现 RESTful API 的 todo list, 同时支持form操作
  • 《深入 React 技术栈》
  • CODING 缺陷管理功能正式开始公测
  • CSS魔法堂:Absolute Positioning就这个样
  • hadoop集群管理系统搭建规划说明
  • HTTP请求重发
  • JAVA 学习IO流
  • Javascript 原型链
  • Java教程_软件开发基础
  • mysql中InnoDB引擎中页的概念
  • PAT A1092
  • PHP变量
  • socket.io+express实现聊天室的思考(三)
  • TCP拥塞控制
  • 开源SQL-on-Hadoop系统一览
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 排序算法学习笔记
  • 使用 QuickBI 搭建酷炫可视化分析
  • 我有几个粽子,和一个故事
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 正则表达式-基础知识Review
  • #pragma pack(1)
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (八)c52学习之旅-中断实验
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (汇总)os模块以及shutil模块对文件的操作
  • (九)One-Wire总线-DS18B20
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .net wcf memory gates checking failed
  • .NET的数据绑定
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • @JsonSerialize注解的使用
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • @property @synthesize @dynamic 及相关属性作用探究