springboot整合websocket高级版
上一章节我们说了websocket的优缺点,我们通过websocket和http的对比分析,总结出用websocket的场景。今天小编带大家通过一个案例使用下升级版的websocket。
sockjs介绍
So长江J算是一个浏览器库,它提供了一个跨浏览器的api , 他在浏览器和服务端建立了一个低延迟、全双工、跨域通信通道。
产生的原因
向ie这些浏览器可能缺少对websocket的支持,我们上一章节也是在谷歌浏览器下开发完成的。这里对ie这些浏览器没有做测试,但是一些低版本的浏览器的确是不支持的websocket的。
sockJs对浏览器兼容性很大。在原声的websocket基础上进行了优化。sockjs在不支持websocket的浏览器上会采用轮询的方式实现双向通信。
环境搭建
springboot整合sockjs
springboot 对sockjs支持性很良好。只需要在原有的websocket配置上添加已sockjs方式发布就可以了。
@Configuration
//注解开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping,就像使用@RequestMapping一样
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {//注册STOMP协议的节点(endpoint),并映射指定的url
//注册一个STOMP的endpoint,并指定使用SockJS协议
registry.addEndpoint("/endpointAric")
.setAllowedOrigins("*")
.addInterceptors(createSessionInterceptor())
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理(Message Broker)
//广播式应配置一个/topic消息代理
registry.enableSimpleBroker("/topic", "/queue");
//registry.setApplicationDestinationPrefixes("/app");
//点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是/user/
registry.setUserDestinationPrefix("/user/");
}
/**
* 配置客户端入站通道拦截器
*/
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(createUserInterceptor());
}
@Bean
public HandshakeInterceptor createSessionInterceptor(){
return new SessionAuthHandshakeInterceptor();
}
/*将客户端渠道拦截器加入spring ioc容器*/
@Bean
public UserInterceptor createUserInterceptor() {
return new UserInterceptor();
}
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(500 * 1024 * 1024);
registration.setSendBufferSizeLimit(1024 * 1024 * 1024);
registration.setSendTimeLimit(200000);
}
}
registry.enableSimpleBroker("/topic", "/queue");
设置的topic,queue就是客户端和服务端的通信通道。
使用场景
本节内容我们将通过聊天室体验下websocket的使用。
聊天室开发
上面我们已经配置了服务端的环境,这样我们就可以开发通道内的通信内容。聊天室使用websocket进行通信解决了我们通过ajax调用的实时性。保证了消息的准确性。无延后性。
点对点通信
/*点对点通信*/
@MessageMapping(value = "/sendToUser")
public void templateTest1(@Payload String message, @Header("userId") String userId,
@Headers Map<String, Object> headers) {
int i = 1;
for (SimpUser user : userRegistry.getUsers()) {
System.out.println("用户" + i++ + "---" + user);
}
CustomUser userInfo = (CustomUser) ((Map)(headers.get("simpSessionAttributes"))).get(CoreConstants.USERINFO);
String fromUserId = String.valueOf(userInfo.getUserId());
//发送消息给指定用户
messagingTemplate.convertAndSendToUser(userId, "/queue/message",new AricResponse(fromUserId,userId,message));
if (!fromUserId.equals(userId)) {
//给自己发送一条,消息同步
messagingTemplate.convertAndSendToUser(fromUserId, "/queue/message",new AricResponse(fromUserId,userId,message));
}
//消息新增
messageService.insertBackMessage(fromUserId,userId,message);
}
@MessageMapping(value = "sendToUser")
该注解实现了接受客户端的请求。对应客户端可以通过
stompClient.send("/sendToUser", {'userId': userId},content);
进行发送至服务端,userId是客户端用户发送给指定用户的id, content是发送的内容
服务端通过@Payload和@Header注解接受前端传送的信息。上述代码中获取发送者用户id的地方为什么那么写呢。下面我们看看客户端连接的方式
// 建立连接对象(还未发起连接)
socket = new SockJS(host+"/endpointAric");
// 获取 STOMP 子协议的客户端对象
stompClient = Stomp.over(socket);
// 向服务器发起websocket连接并发送CONNECT帧
stompClient.connect(
{
userId: currentUser.userId // 携带客户端信息
},
function connectCallback(frame) {
// 连接成功时(服务器响应 CONNECTED 帧)的回调方法
subscribe();
console.log("连接成功");
},
function errorCallBack(error) {
// 连接失败时(服务器响应 ERROR 帧)的回调方法
console.log("连接失败"+error);
if (errorTimes < 10) {
errorTimes++;
setTimeout("connect();",8000);
}
}
);
在连接的时候客户端会将当前用户的id传递进来,这里也解释了为什么服务端那样获取用户信息。然后就通过/queue/message
发送给指定的用户。因为我们在配置websocket的时候指定了
registry.setUserDestinationPrefix("/user/");
,所以服务端发送给/queue/message
了,客户端订阅的时候需要加上user 即 /user/queue/message
function subscribe() {
stompClient.subscribe('/user/queue/message', function (response) {
var returnData = JSON.parse(response.body);
if (returnData.fromUserId == returnData.toUserId) {
//自己发送的消息需要自己渲染到聊天框中
setMessageInnerHTML(currentUser.userId, returnData, 0);
} else if (returnData.fromUserId == currentUser.userId) {
//自己发送信息给别,自己收到的信息
setMessageInnerHTML(returnData.toUserId, returnData, 1);
} else {
//别人发送的信息
setMessageInnerHTML(returnData.fromUserId, returnData, 0);
}
});
}
群聊
/**
* 多房间聊天室
* @param chatRoomId
* @param message
* @return
*/
@MessageMapping("/welcome/{chatRoomId}") //当浏览器向服务端发送请求时,通过@MessageMapping映射/welcome这个地址,类似于@ResponseMapping
@SendTo("/topic/getResponse/{chatRoomId}")//当服务器有消息时,会对订阅了@SendTo中的路径的浏览器发送消息
public AricResponse say(@Header("userId") String userId,@DestinationVariable("chatRoomId") String chatRoomId, AricMessage message) {
try {
//睡眠1秒
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AricResponse(userId,null,"welcome," + message.getName()+chatRoomId + "!");
}
群聊相对与单聊简单很多,我们发送信息的时候只需要发送到房间通道内就行。而在次群聊内的人只需要订阅房号的信息就行了。这里代码不在赘述。有疑问的小伙伴可以通过下方加入战队找到我。
效果
总结
sockjs在websocket基础上进行各个浏览器的兼容,让我们的开发变得友好起来。
如果你使用Java做服务端,同时又恰好使用Spring Framework作为框架,那么推荐使用SockJS,因为Spring Framework本身就是SockJS推荐的Java Server实现,同时也提供了Java 的client实现。
如果你使用Node.js做服务端,那么毫无疑问你该选择Socket.IO,它本省就是从Node.js开始的,当然服务端也提供了engine.io-server-java实现。甚至你可以使用
加入战队
微信公众号
springboot整合websocket高级版的更多相关文章
- springboot整合websocket原生版
目录 HTTP缺点 HTTP websocket区别 websocket原理 使用场景 springboot整合websocket 环境准备 客户端连接 加入战队 微信公众号 主题 HTTP请求用于我 ...
- SpringBoot 整合 WebSocket
SpringBoot 整合 WebSocket(topic广播) 1.什么是WebSocket WebSocket为游览器和服务器提供了双工异步通信的功能,即游览器可以向服务器发送消息,服务器也可以向 ...
- SpringBoot整合Mybatis注解版---update出现org.apache.ibatis.binding.BindingException: Parameter 'XXX' not found. Available parameters are [arg1, arg0, param1, param2]
SpringBoot整合Mybatis注解版---update时出现的问题 问题描述: 1.sql建表语句 DROP TABLE IF EXISTS `department`; CREATE TABL ...
- Springboot整合Websocket遇到的坑
Springboot整合Websocket遇到的坑 一.使用Springboot内嵌的tomcat启动websocket 1.添加ServerEndpointExporter配置bean @Confi ...
- SpringBoot整合websocket简单示例
依赖 <!-- springboot整合websocket --> <dependency> <groupId>org.springframework.boot&l ...
- WebSocket的简单认识&SpringBoot整合websocket
1. 什么是WebSocket?菜鸟对websocket的解释如下 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务 ...
- springboot整合WebService简单版
一.什么是webservice 关于webservice的介绍摘自百度百科,上面的介绍很详细.(链接:https://baike.baidu.com/item/Web%20Service/121503 ...
- springboot整合websocket实现客户端与服务端通信
定义 WebSocket是通过单个TCP连接提供全双工(双向通信)通信信道的计算机通信协议.此WebSocket API可在用户的浏览器和服务器之间进行双向通信.用户可以向服务器发送消息并接收事件驱 ...
- Springboot整合WebSocket实现网页版聊天,快来围观!
随机推荐
- Visual Studio中Es6的开发环境搭建
1.打开终端,输入初始化代码.输入代码之后会在目录中出现package.json,可以在红色下划线上写上作者名和描述(不写也可以) npm init -y 2.安装Babel转换器 npm in ...
- c语言学习书籍推荐《C语言学习路线图•C语言必须知道的300个问题》下载
下载地址:点我 <C语言学习路线图•C语言必须知道的300个问题>以基础知识为框架,介绍了c语言各部分知识所对应的常见开发疑难问题,并作了透彻地解析.<C语言学习路线图•C语言必须知 ...
- Java项目案例之--封装的实例
Java项目案例之---封装的实例 有一个专业类,有一个专业对象,专业名称:计算机科学与技术,专业编号:J001,专业年限:4,对年限添加约束,如果输入小于0,则默认为0,否则显示输入的值 有一个学生 ...
- CDQZ集训DAY0 日记
貌似没发生什么事…… 按照教练员的交代,写一下流水账…… 早上5:30到了机场,然后就默默地坐着飞机到了成都.然后就按预定好的被GXY的父亲的朋友接机(貌似因为觉得GXY和他爸的同学挺像被批判一番). ...
- 批量替换git目录的远程仓库URL地址脚本
需求: 1. 输入work-dir 工作目录 2. 扫描工作目录中的子目录 3. 对每一个子目录, 判断是否是git repo 4. 确认是git repo, 获取git origin remote- ...
- Excel催化剂开源第22波-VSTO的帮助文档在哪里?
Excel催化剂开源第22波-VSTO的帮助文档在哪里? Excel催化剂 2019.01.12 14:10 字数 2930 阅读 55评论 0喜欢 0 编辑文章 对于专业程序猿来说,查找文档不是 ...
- python面向过程编程 - ATM
前面程序整合加自定义日志 1.文件摆放 ├── xxxx │ ├── src.py │ └── fil_mode.py │ └── data_time.py │ └── loading.py │ └─ ...
- Visual Studio 调试系列1 Debug 与 Release 模式
系列目录 [已更新最新开发文章,点击查看详细] Debug 模式 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序. 在Debug模式下调试,可以在断点处看到 ...
- Java 虚拟机部分面试题
Java虚拟机部分的面试内容包括三部分:GC.类加载机制以及内存 Java内存区域 JVM内存分为哪几部分,这些部分分别都存储哪些数据? 线程隔离的数据区:程序计数器.Java虚拟机栈.本地方法栈. ...
- Simple TPU的设计和性能评估
深度学习飞速发展过程中,人们发现原有的处理器无法满足神经网络这种特定的大量计算,大量的开始针对这一应用进行专用的硬件设计.谷歌的张量处理单元(Tensor Processing Unit,后文简称TP ...