Java中Springboot websocket怎么用
发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,这篇文章将为大家详细讲解有关Java中Springboot websocket怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。什么是WebSocketWebSo
千家信息网最后更新 2025年02月23日Java中Springboot websocket怎么用
这篇文章将为大家详细讲解有关Java中Springboot websocket怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
什么是WebSocket
WebSocket是一种在单个TCP连接上进行全双工通信的协议 …
为什么要实现握手监控管理
如果说,连接随意创建,不管的话,会存在错误,broken pipe
表面看单纯报错,并没什么功能缺陷等,但实际,请求数增加,容易导致系统奔溃。这边画重点。
出现原因有很多种,目前我这边出现的原因,是因为客户端已关闭连接,服务端还持续推送导致。
如何使用
下面将使用springboot集成的webSocket
导入Maven
首先SpringBoot版本
org.springframework.boot spring-boot-starter-parent 1.5.8.RELEASE
集成websocket
// 加个web集成吧org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-websocket
Java代码
Config配置
首先,我们需要重写WebSocketHandlerDecoratorFactory
主要用来监控客户端握手连接进来以及挥手关闭连接
代码
需要一个管理Socket的类
package com.li.manager;import lombok.extern.slf4j.Slf4j;import org.springframework.web.socket.WebSocketSession;import java.util.concurrent.ConcurrentHashMap;/** * socket管理器 */@Slf4jpublic class SocketManager { private static ConcurrentHashMapmanager = new ConcurrentHashMap (); public static void add(String key, WebSocketSession webSocketSession) { log.info("新添加webSocket连接 {} ", key); manager.put(key, webSocketSession); } public static void remove(String key) { log.info("移除webSocket连接 {} ", key); manager.remove(key); } public static WebSocketSession get(String key) { log.info("获取webSocket连接 {}", key); return manager.get(key); }}
package com.li.factory;import com.li.manager.SocketManager;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.WebSocketHandlerDecorator;import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;import java.security.Principal;/** * 服务端和客户端在进行握手挥手时会被执行 */@Component@Slf4jpublic class WebSocketDecoratorFactory implements WebSocketHandlerDecoratorFactory { @Override public WebSocketHandler decorate(WebSocketHandler handler) { return new WebSocketHandlerDecorator(handler) { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { log.info("有人连接啦 sessionId = {}", session.getId()); Principal principal = session.getPrincipal(); if (principal != null) { log.info("key = {} 存入", principal.getName()); // 身份校验成功,缓存socket连接 SocketManager.add(principal.getName(), session); } super.afterConnectionEstablished(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { log.info("有人退出连接啦 sessionId = {}", session.getId()); Principal principal = session.getPrincipal(); if (principal != null) { // 身份校验成功,移除socket连接 SocketManager.remove(principal.getName()); } super.afterConnectionClosed(session, closeStatus); } }; }}
注意:以上session变量,需要注意两点,一个是getId(),一个是getPrincipal().getName()
getId() : 返回的是唯一的会话标识符。
getPrincipal() : 经过身份验证,返回Principal实例,未经过身份验证,返回null
Principal: 委托人的抽象概念,可以是公司id,名字,用户唯一识别token等
当你按上面代码使用,你会发现getPrincipal()返回null,为什么?这边还需要重写一个DefaultHandshakeHandler
代码
package com.li.handler;import lombok.extern.slf4j.Slf4j;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServletServerHttpRequest;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.server.support.DefaultHandshakeHandler;import javax.servlet.http.HttpServletRequest;import java.security.Principal;import java.util.Map;/** * 我们可以通过请求信息,比如token、或者session判用户是否可以连接,这样就能够防范非法用户 */@Slf4j@Componentpublic class PrincipalHandshakeHandler extends DefaultHandshakeHandler { @Override protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Mapattributes) { /** * 这边可以按你的需求,如何获取唯一的值,既unicode * 得到的值,会在监听处理连接的属性中,既WebSocketSession.getPrincipal().getName() * 也可以自己实现Principal() */ if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) request; HttpServletRequest httpRequest = servletServerHttpRequest.getServletRequest(); /** * 这边就获取你最熟悉的陌生人,携带参数,你可以cookie,请求头,或者url携带,这边我采用url携带 */ final String token = httpRequest.getParameter("token"); if (StringUtils.isEmpty(token)) { return null; } return new Principal() { @Override public String getName() { return token; } }; } return null; }}
需要的东西都有了,那准备装载吧
代码
package com.li.config;import com.li.factory.WebSocketDecoratorFactory;import com.li.handler.PrincipalHandshakeHandler;import org.springframework.beans.factory.annotation.Autowired;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;import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;/** * WebSocketConfig配置 */@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Autowired private WebSocketDecoratorFactory webSocketDecoratorFactory; @Autowired private PrincipalHandshakeHandler principalHandshakeHandler; @Override public void registerStompEndpoints(StompEndpointRegistry registry) { /** * myUrl表示 你前端到时要对应url映射 */ registry.addEndpoint("/myUrl") .setAllowedOrigins("*") .setHandshakeHandler(principalHandshakeHandler) .withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { /** * queue 点对点 * topic 广播 * user 点对点前缀 */ registry.enableSimpleBroker("/queue", "/topic"); registry.setUserDestinationPrefix("/user"); } @Override public void configureWebSocketTransport(WebSocketTransportRegistration registration) { registration.addDecoratorFactory(webSocketDecoratorFactory); super.configureWebSocketTransport(registration); }}
终于完成了
最后,来一个通过http请求,将其发送到客户端
代码
package com.li.controller;import com.li.manager.SocketManager;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.messaging.handler.annotation.MessageMapping;import org.springframework.messaging.handler.annotation.SendTo;import org.springframework.messaging.simp.SimpMessagingTemplate;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.socket.WebSocketSession;import java.util.Map;@RestController@Slf4jpublic class TestController { @Autowired private SimpMessagingTemplate template; /** * 服务器指定用户进行推送,需要前端开通 var socket = new SockJS(host+'/myUrl' + '?token=1234'); */ @RequestMapping("/sendUser") public void sendUser(String token) { log.info("token = {} ,对其发送您好", token); WebSocketSession webSocketSession = SocketManager.get(token); if (webSocketSession != null) { /** * 主要防止broken pipe */ template.convertAndSendToUser(token, "/queue/sendUser", "您好"); } } /** * 广播,服务器主动推给连接的客户端 */ @RequestMapping("/sendTopic") public void sendTopic() { template.convertAndSend("/topic/sendTopic", "大家晚上好"); } /** * 客户端发消息,服务端接收 * * @param message */ // 相当于RequestMapping @MessageMapping("/sendServer") public void sendServer(String message) { log.info("message:{}", message); } /** * 客户端发消息,大家都接收,相当于直播说话 * * @param message * @return */ @MessageMapping("/sendAllUser") @SendTo("/topic/sendTopic") public String sendAllUser(String message) { // 也可以采用template方式 return message; } /** * 点对点用户聊天,这边需要注意,由于前端传过来json数据,所以使用@RequestBody * 这边需要前端开通var socket = new SockJS(host+'/myUrl' + '?token=4567'); token为指定name * @param map */ @MessageMapping("/sendMyUser") public void sendMyUser(@RequestBody Mapmap) { log.info("map = {}", map); WebSocketSession webSocketSession = SocketManager.get(map.get("name")); if (webSocketSession != null) { log.info("sessionId = {}", webSocketSession.getId()); template.convertAndSendToUser(map.get("name"), "/queue/sendUser", map.get("message")); } }}
前端代码
可以直接启动
Spring Boot WebSocket+广播式
关于"Java中Springboot websocket怎么用"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
客户
客户端
代码
前端
消息
用户
服务
地址
路径
身份
广播
配置
篇文章
监听
管理
不同
成功
您好
原因
可以通过
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
数据库动态表创建删除
数据库在电脑上如何设置
开一家软件开发公司成本
国内用什么交友软件开发
2台笔记本如何传输数据库
怎么访问内网数据库
谷歌 社招 网络安全
网络安全知识观后感300字
人武部学习网络安全
莆田易趣网络技术有限公司
宁波订制app软件开发
银河破坏者数据库
网络安全在校园 手抄报方案
软件开发步骤包括哪些过程
上海服务器好还是北京
如何软件开发学习
sql里的数据库不响应
网络安全共性基础教程
软件开发故事地图
软件开发工程师的胜任力
扬州服务器工控机定制
软件开发的主要职责和要求
关系型数据库的特性
嘉定区软件开发费用
p盘服务器教程视频
海口网络软件开发公司
服务器配置底层管理ip
网络安全概述课后题答案
微信好友隐藏软件开发
吐鲁番网络技术参数