千家信息网

Java中Springboot websocket怎么用

发表于:2025-01-16 作者:千家信息网编辑
千家信息网最后更新 2025年01月16日,这篇文章将为大家详细讲解有关Java中Springboot websocket怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。什么是WebSocketWebSo
千家信息网最后更新 2025年01月16日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 ConcurrentHashMap manager = 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, Map attributes) {        /**         * 这边可以按你的需求,如何获取唯一的值,既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 Map map) {        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安全错误 数据库的锁怎样保障安全 建立民营企业创新人才数据库 浙江众智工场互联网科技 什么类型的公司会购买服务器主板 以数据库为 bdf数据库 半军工企业网络安全 团委网络安全宣传周条幅 数据库的构建采用什么 sql服务器管理查看在哪 金蝶破解版找不到服务器 网络安全应急工作会议 戴尔服务器格式化磁盘 网络安全知识大闯关 杨浦区营销软件开发程序 游戏软件开发需要学习英文吗 我的世界如何在服务器上安装模组 软件开发 看板 长沙系统结算软件开发有限公司 阿里云服务器加java gridreport图表怎么绑定数据库 服务器管理员权限禁止访问 畅捷通t3数据库备份文件在哪里 根据网络安全法 协助 目前的网络安全威胁有哪些 网络技术服务岗招聘考试试题 部队网络安全招聘 网络安全隐患亮点 服务器管理地址是什么东西 网络安全是国家安全的核心对不对 乌鲁木齐app手机软件开发
0