WebSocket 实现前后端通信的笔记

之前在做站内信时,用到了 WebSocket ,整理了一些笔记分享如下。
本文基于 SpringBoot 2.1.5,本文不涉及环境搭建。

引入依赖

在 Spring 中要使用 WebSocket 功能,需要在pom中引入依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

配置类

增加一个配置类,用于定义 WebSocket 全局配置信息

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {/*** 注册stomp端点* @param registry*/@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {## 允许使用socketJs方式访问 即可通过http://IP:PORT/xboot/ws来和服务端websocket连接registry.addEndpoint("/tmax/ws").setAllowedOrigins("*").withSockJS();}/*** 配置信息代理* @param registry*/@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {## 订阅Broker名称 user点对点 topic广播即群发registry.enableSimpleBroker("/user","/topic");## 全局(客户端)使用的消息前缀registry.setApplicationDestinationPrefixes("/app");## 点对点使用的前缀 无需配置 默认/userregistry.setUserDestinationPrefix("/user");}
}

来看一下这两个方法:

1、registerStompEndpoints(StompEndpointRegistry registry)

注册stomp端点。起到的作用就是添加一个服务端点,来接收客户端的连接,
registry.addEndpoint("/tmax/ws") 表示添加了一个 /tmax/ws 端点,客户端可以通过这个端点来进行连接。withSockJS() 的作用是开启 SockJS 访问支持,即可通过http://IP:PORT/tmax/ws 来和服务端 websocket 连接。

2、configureMessageBroker(MessageBrokerRegistry registry)

配置信息代理。定义消息代理,设置消息连接请求的各种规范信息。
registry.enableSimpleBroker("/user","/topic") 表示客户端订阅地址的前缀信息,也就是客户端接收服务端消息的地址的前缀信息(比较绕,看完整个例子,大概就能明白了)registry.setApplicationDestinationPrefixes("/app") 指服务端接收地址的前缀,意思就是说客户端给服务端发消息的地址的前缀。
registry.setUserDestinationPrefix("/user") 指推送用户前缀。

我不不难发现,setApplicationDestinationPrefixessetUserDestinationPrefix 起到的效果敲好相反,一个定义了客户端接收的地址前缀,一个定义了客户端发送地址的前缀。

开始业务代码的编写

先了解几个知识点,下方会用到。

1、MessageMapping

接收客户端请求连接注解。Spring 对于 WebSocket 封装的特别简单,提供了一个 @MessageMapping 注解,功能类似 @RequestMapping,它是存在于Controller中的,定义一个消息的基本请求,功能也跟 @RequestMapping类似,包括支持通配符 的url定义等等。

2、SimpMessagingTemplate

SimpMessagingTemplate 是 Spring-WebSocket 内置的一个消息发送工具,可以将消息发送到指定的客户端。

3、SendTo

@SendTo 可以把消息广播到路径上去,例如下面可以把消息广播到 "/topic/greetings”,如果客户端在这个路径订阅消息,则可以接收到消息

接下来看一下后台代码实现,HelloController

/*** @author niceyoo*/
@Slf4j
@Controller
@Api(description = "hello接口")
@Transactional
public class HelloController {@Autowiredprivate SimpMessagingTemplate messagingTemplate;/*** 跳转至hello.html界面* @return*/@RequestMapping("/hello")public String hello(){return "hello";}/*** 接收然后转发至客户端消息* @param message* @return* @throws Exception*/@MessageMapping("/top")@SendTo("/topic/greetings")public String greeting(String message) throws Exception {System.out.println("receiving " + message);System.out.println("connecting successfully.");return "AAA:"+message;}/*** 推送消息* @return*/@ResponseBody@RequestMapping("/hello/addMessage")public Result<Object> addMessage(){messagingTemplate.convertAndSend("/topic/greetings", "您收到了新的系统消息");return new ResultUtil<Object>().setSuccessMsg("添加成功");}}

hello.html 代码:

<!doctype html>
<html>
<head><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script><script src="https://cdn.bootcss.com/sockjs-client/1.3.0/sockjs.js"></script><script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script><style>.box {width: 300px;float: left;margin: 0 20px 0 20px;}.box div, .box input {border: 1px solid;-moz-border-radius: 4px;border-radius: 4px;width: 100%;padding: 0px;margin: 5px;}.box div {border-color: grey;height: 300px;overflow: auto;}.box input {height: 30px;}h1 {margin-left: 30px;}body {background-color: #F0F0F0;font-family: "Arial";}</style>
</head>
<body lang="en">
<h1>Index</h1>
<div id="first" class="box"><div></div><input autocomplete="off" value="Type here..."></input><button onclick="connect()">登陆客户端</button><button onclick="send()">发送消息</button>
</div>
<script>var stompClient = null;var sockjs_url = '/tmax/ws';function connect() {var sockjs = new SockJS(sockjs_url);stompClient = Stomp.over(sockjs);stompClient.connect({}, function(frame) {console.log('Connected: ' + frame);stompClient.subscribe('/topic/greetings', function(greeting){console.log("返回内容:"+greeting.body);print('服务器:', greeting.body);});});}function send() {if(stompClient == null){print('系统提示:', '请先点击客户端登陆');return false;}print('客户端:', inp.val());stompClient.send("/app/top", {}, inp.val());inp.val('');}$('#first input').focus();var div  = $('#first div');var inp  = $('#first input');var print = function(m, p) {p = (p === undefined) ? '' : p;div.append($("<code>").text(m + ' ' + p));div.append($("<br>"));div.scrollTop(div.scrollTop()+10000);};</script>
</body>
</html>

操作流程:

点击“登录客户端”,输入框内输入内容,点击发送消息。

消息推送

关于消息的推送,借助 postman,调用 http://127.0.0.1:8888/hello/addMessage,实现后端推送至客户端。

额外补充,关于消息推送,往往会用到推送至指定用户,则:messagingTemplate.convertAndSendToUser(id,"/queue/subscribe", “您收到了新的消息”); ,其中id为系统用户id。

详细可搜索 SimpMessagingTemplate 的一些用法。

如果文章有错的地方欢迎指正,大家互相留言交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:niceyoo

参考地址:https://www.jianshu.com/p/60799f1356c5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/414446.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 地图搜索商家,检索关键字(高德地图,百度地图),地址搜索

1、高德地图 实现效果 打印数据 实现步骤&#xff1a; 1、首先去高德开放平台注册应用 高德开放平台&#xff1a;https://lbs.amap.com/ 2、点击 我的应用 ——>设置 注&#xff1a;SHA1获取方法&#xff1a;https://blog.…

全局异常捕获处理-@ControllerAdvice+@HandleException

涂涂影院管理系统这个demo中有个异常管理的标签&#xff0c;用于捕获 涂涂影院APP用户异常信息 &#xff0c;有小伙伴好奇&#xff0c;排除APP&#xff0c;后台端的是如何处理全局异常的&#xff0c;故项目中的实际应用已记之。 关于目前的异常处理 在使用全局异常处理之前&am…

前端学习(2791):实现上拉加载更多

判断页面是否有十条数据 没有 则消失

2019金球奖——梅西

在公元2019年12月3日&#xff0c;梅西加冕金球奖六冠王&#xff0c;今天我是梅西&#xff0c;今天属于梅西&#xff0c;祝贺梅西&#xff01; 王者气质 十全十美 实至名归 六金闪耀 蓦然回首&#xff0c;已是十年信仰

定时任务 Scheduled quartz

在项目应用中往往会用到任务定时器的功能&#xff0c;比如某某时间&#xff0c;或者多少多少秒然后执行某个骚操作等。 spring 支持多种定时任务的实现&#xff0c;其中不乏自身提供的定时器。 接下来介绍一下使用 spring 的定时器和使用 quartz 定时器。 前言 spring 自身提供…

前端学习(2792):下拉刷新

开启下拉刷新 延迟下拉刷新 解决下拉刷新 传递callback有就刷新 无就不刷新

Android 获取短信验证码,自动填充

1、申请权限 <uses-permission android:name"android.permission.RECEIVE_SMS" /> <uses-permission android:name"android.permission.READ_SMS" /> API>23动态申请权限 private static final String[] authBaseArr {//申请类型Manife…

spring-boot-starter-parent

一、你的项目 pom.xml 中有这段代码吗 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.5.RELEASE</version><relativePath/> </parent>idea &…

项目集成Spring Security

前言 之前写的 涂涂影院管理系统 这个 demo 是基于 shiro 来鉴权的&#xff0c;项目前后端分离后&#xff0c;显然集成 Spring Security 更加方便一些&#xff0c;毕竟&#xff0c;都用 Spring 了&#xff0c;权限管理当然 Spring Security. 花了半天时间整理的笔记&#xff0…

android 使用AIDL实现进程间通讯

一、创建服务端 1、首先创建AIDL文件 2、创建service&#xff0c;绑定AIDL接口 3、配置service <service android:name".AidlService"android:enabled"true"android:exported"true"><intent-filter android:priority"1000"&…

大数据入门第二十天——scala入门(二)scala基础02

一、 类、对象、继承、特质 1.类 Scala的类与Java、C的类比起来更简洁 定义&#xff1a; package com.jiangbei //在Scala中&#xff0c;类并不用声明为public。 //Scala源文件中可以包含多个类&#xff0c;所有这些类都具有公有可见性。 class Person {// 定义一个不可变的val…

SpringSecurity 整合 JWT

项目集成Spring Security&#xff08;一&#xff09; 在上一篇基础上继续集成 JWT &#xff0c;实现用户身份验证。 前言 前后端分离项目中&#xff0c;如果直接把 API 接口对外开放&#xff0c;我们知道这样风险是很大的&#xff0c;所以在上一篇中我们引入了 Spring Securit…