学习笔记053——实现WebSocket

nodejs mysql 更新_nodejs推送mysql数据更新到前端显示 nodejs推送mysql数据更新到前端显示如下所示,是一些参考程序,虚妄对你们有所帮助:001 server.js002 //建立MySQL连接, 根据自己环境修改相应的数据库信息003 var app = require('http').createServer(handler),004 io = require('socket.io').listen(app),005 fs = requir... 阅读详情

1、Java原生实现

1.1、导入重要依赖

<!-- Java原生代码实现websocket依赖 -->
<dependency>
    <groupId>org.java-websocket</groupId>
    <artifactId>Java-WebSocket</artifactId>
    <version>1.5.3</version>
</dependency>

1.2、继承WebSocketServer

import java.net.InetSocketAddress;
import java.net.UnknownHostException;

import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

/**
 * @author HTL
 * @version 2024-7-8  008
 * @since JDK8
 */
public class SocketServer extends WebSocketServer {

    public SocketServer(int port) throws UnknownHostException {
        super(new InetSocketAddress(port));
    }

    public SocketServer(InetSocketAddress address) {
        super(address);
    }

    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake) {
        conn.send("Welcome to the server!"); // This method sends a message to the new client
        broadcast("new connection: " + handshake
                .getResourceDescriptor()); // This method sends a message to all clients connected
        System.out.println(
                conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");

    }

    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote) {
        broadcast(conn + " has left the room!");
        System.out.println(conn + " has left the room!");
    }
    

    @Override
    public void onMessage(WebSocket conn, String message) {
        broadcast(message);
        System.out.println(conn + " 发送数据: " + message);
    }


    @Override
    public void onError(WebSocket conn, Exception ex) {
        ex.printStackTrace();
        if (conn != null) {
            // some errors like port binding failed may not be assignable to a specific
            // websocket
        }

    }

    @Override
    public void onStart() {
        System.out.println("Server started!");
        setConnectionLostTimeout(0);
        setConnectionLostTimeout(100);

    }

}

1.3、测试

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author HTL
 * @version 2024-7-8  008
 * @since JDK8
 */
public class SocketTest {

    public static void main(String[] args) throws InterruptedException, IOException {
        int port = 8887; // 端口

        SocketServer s = new SocketServer(port);
        s.start();
        System.out.println("ChatServer started on port: " + s.getPort());

        BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String in = sysin.readLine();
            s.broadcast(in);
            if (in.equals("exit")) {
                s.stop(1000);
                break;
            }
        }
    }

}

# 请求地址
ws://127.0.0.1:8887

2、SpringBoot实现

2.1、导入依赖

<!-- 2、SpringBoot实现websocket 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2.2、编写配置类

import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author HTL
 * @version 2024-7-4  004
 * @since JDK8
 */
public class WsSessionManager {
    /**
     * 保存连接 session 的地方
     */
    private static ConcurrentHashMap<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>();

    /**
     * 添加 session
     *
     * @param key
     */
    public static void add(String key, WebSocketSession session) {
        // 添加 session
        SESSION_POOL.put(key, session);
    }

    /**
     * 删除 session,会返回删除的 session
     *
     * @param key
     * @return
     */
    public static WebSocketSession remove(String key) {
        // 删除 session
        return SESSION_POOL.remove(key);
    }

    /**
     * 删除并同步关闭连接
     *
     * @param key
     */
    public static void removeAndClose(String key) {
        WebSocketSession session = remove(key);
        if (session != null) {
            try {
                // 关闭连接
                session.close();
            } catch (IOException e) {
                // todo: 关闭出现异常处理
                e.printStackTrace();
            }
        }
    }

    /**
     * 获得 session
     *
     * @param key
     * @return
     */
    public static WebSocketSession get(String key) {
        // 获得 session
        return SESSION_POOL.get(key);
    }
}

继承TextWebSocketHandler

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

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

/**
 * @author HTL
 * @version 2024-7-4  004
 * @since JDK8
 */
@Component
public class HttpAuthHandler extends TextWebSocketHandler {

    /**
     * socket 建立成功事件
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Object sessionId = session.getAttributes().get("session_id");
        if (sessionId != null) {
            // 用户连接成功,放入在线用户缓存
            WsSessionManager.add(sessionId.toString(), session);
        } else {
            throw new RuntimeException("用户登录已经失效!");
        }
    }

    /**
     * 接收消息事件
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 获得客户端传来的消息
        String payload = message.getPayload();
        Object sessionId = session.getAttributes().get("session_id");
        SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        myFormat.format(new Date());
        System.out.println(myFormat.format(new Date()) + " ——> server 接收到:" + sessionId + " 发送的内容:" + payload);
        session.sendMessage(new TextMessage(myFormat.format(new Date()) + " ——> server 返回给:" + sessionId + " 的消息:" + payload));
    }

    /**
     * socket 断开连接时
     *
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Object sessionId = session.getAttributes().get("session_id");
        if (sessionId != null) {
            // 用户退出,移除缓存
            WsSessionManager.remove(sessionId.toString());
        }
    }


}

实现HandshakeInterceptor

import java.util.Map;

import org.apache.logging.log4j.util.Strings;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

/**
 * @author HTL
 * @version 2024-7-4  004
 * @since JDK8
 */
@Component
public class MyInterceptor implements HandshakeInterceptor {

    /**
     * 握手前
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        System.out.println("握手开始");
        String hostName = request.getRemoteAddress().getHostName();
        String sessionId = hostName+String.valueOf((int)(Math.random()*1000));
        if (Strings.isNotBlank(sessionId)) {
            // 放入属性域
            attributes.put("session_id", sessionId);
            System.out.println("用户 session_id:" + sessionId + " 握手成功!");
            return true;
        }
        System.out.println("用户登录已失效");
        return false;
    }

    /**
     * 握手后
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
        System.out.println("握手完成");
    }

}


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

/**
 * @author HTL
 * @version 2024-7-4  004
 * @since JDK8
 */
@Configuration
@EnableWebSocket
public class WebsocketConfig implements WebSocketConfigurer {

    @Autowired
    private HttpAuthHandler httpAuthHandler;

    @Autowired
    private MyInterceptor myInterceptor;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry
                .addHandler(httpAuthHandler, "myWS")//请求地址前缀
                .addInterceptors(myInterceptor)
                .setAllowedOrigins("*");
    }

}

Java实现Excel转PDF高保真转换:Aspose.Cells深度实践与调优 文档格式转换是数据处理与系统集成中的常见需求,其核心在于确保内容与样式在不同格式间准确传递。从技术原理上看,这涉及文件结构的解析、样式属性的映射以及目标格式的精准渲染。在Java生态中,Apache POI等开源库虽能实现基础转换,但在处理复杂样式、图表、字体嵌入等细节时,往往难以达到商业级保真度,影响文档的专业性与一致性。Aspose.Cells作为商业级组件,通过深度模拟Office原生渲染引擎,提供了近乎完美的视觉还原能力,成为财务报告、审计文档、合同生成等对格式一致性要求严苛场景的理想选择。本文聚焦 阅读详情

相关推荐

Gemini 2.5 Pro直喂式代码分析:零配置实现全项目上下文理解

代码分析本质是结构化语义理解问题,其核心在于保留import、class、函数调用等跨文件上下文链接。传统RAG方案因切块导致语义断裂、向量失真和工程冗余,难以支撑精准的代码重构与安全审计。Gemini 2.5 Pro凭借100万token原生长上下文与多语言MIME Type感知能力(如text/x-python、text/typescript),支持ZIP整包直喂,天然维持AST级结构完整性。该技术路径显著提升硬编码识别、环境变量迁移、SQL注入修复等高频开发任务的准确率与响应速度,已落地于Django

cmff98425的博客 466

java 实现 websocket的五种方式

本文主要讲述在Java技术领域实现websocket服务的五种方式.  使用Java原生代码实现websocket服务的方法, 此方法需要引入一个第三方库java-websocket.jar. 截至目前2023/01/01最新版本为1.5.3.  项目源代码位于: https://github.com/TooTallNate/Java-WebSocket  示例代码位于: https://github.com/TooTallNate/Java-WebSocket/tree/master/src/m

萧曳丶 1万+

AAAI2024最佳解读|FontDiffuser One-Shot Font Generation via Denoising Diffusion with Multi-Scal

本文提出了一种名为FontDiffuser的基于扩散的单次字体生成方法,旨在通过去噪扩散模型生成模仿参考图像风格的字体,同时保留源图像的内容。尽管现有的字体生成方法在性能上取得了一定的进展,但在处理复杂字符和大风格变化时仍面临挑战。FontDiffuser通过引入多尺度内容聚合(MCA)模块,有效结合不同尺度的全局和局部内容线索,从而增强复杂字符的笔画保留能力。此外,文章还提出了一种风格对比细化(SCR)模块,用于风格表示学习,利用风格提取器从图像中分离风格,并通过精心设计的风格对比损失来监督扩散模型。

haimianxiaobao11的博客 1189

springboot 中websocket的使用

一.WebSocket简单介绍随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。我们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器...

lpfasd123的博客 2548

提升RAG效果:为何 JSON 格式远胜 Markdown?

在构建强大的 RAG (检索增强生成) 系统时,文档解析是至关重要的第一步。它直接影响着后续的检索效率和生成质量。在众多文档格式中,JSON (JavaScript Object Notation) 格式正逐渐展现出其相对于传统 Markdown 格式的巨大优势。本文将深入探讨 JSON 在 RAG 系统文档解析中的卓越之处,并结合具体案例,让你理解为何 JSON 才是构建下一代智能应用的更优选择。RAG 系统的核心目标是让模型能够利用外部知识库,生成更精准、更贴合实际的答案。

simoncool23的博客 2714

Kafka 系列 —(17)Kafka 流式处理:Kafka Streams架构、使用场景、框架选择

本文介绍了KafkaStreams的架构特点、应用场景及与其他流处理框架的比较。KafkaStreams作为嵌入式分布式流处理库,其核心架构包含流处理器、任务、拓扑和本地状态存储,具备自动容错和伸缩能力。适用于实时监控、ETL、聚合、Join、物化视图等低延迟场景。与Flink、Spark相比,KafkaStreams适合简单架构和微服务,而Flink适合大规模处理,Spark更适合批处理。选择框架需根据具体场景需求,如微服务推荐KafkaStreams,大规模处理推荐Flink。

moton2017的博客 1629

Java Websocket 01: 原生模式 Websocket 基础通信

OnOpen 会注入一个 Session 参数, 这个是实际的 Websocket Session, 其 ID 是全局唯一的, 可以唯一确定一个客户端连接. 在当前版本的实现中, 这是一个从0开始自增的整数. 如果你需要实现例如单个用户登录多个会话, 在通信中, 将消息转发给同一个用户的多个会话, 就要小心记录这些 Session 的 ID.在客户端意外停止后, 服务端会收到 OnError 消息, 可以通过这个消息管理已经关闭的会话。示例是一个普通的 Spring Boot jar项目, 可以通过。

woaimx_1314的博客 295

MPU6050运动中断唤醒STM32低功耗休眠模式实战

本文详细介绍了如何使用MPU6050运动中断唤醒STM32低功耗休眠模式的实战方案。通过配置MPU6050的运动检测中断作为STM32的唤醒源,实现设备在静止时进入低功耗Stop模式,运动时快速唤醒,大幅延长电池续航。涵盖硬件连接、软件配置、参数调试等关键步骤,并提供实际应用案例和优化建议。

rgv23456789的博客 703

Java调用WebSocket的服务端和客户端

用Java语言,实现WebSocket的服务端和客户端

LuckyLay的博客 7111

基于A*算法的二维栅格地图路径规划与避障MATLAB仿真

本文将介绍如何使用MATLAB编写基于A*算法的二维栅格地图路径规划与避障的仿真程序。我们可以使用二维数组表示地图,其中每个元素表示一个栅格的状态,例如1表示障碍物,0表示可行走区域。接下来,我们需要定义A*算法的节点类。G值表示从起始节点到当前节点的代价,H值是启发式函数估计的从当前节点到目标节点的代价。算法,我们可以有效地找到起始点到目标点的最短路径,并在仿真中进行可视化展示。算法的基本思路是从起始节点开始,按照一定的启发式函数选择下一个节点,直到找到目标节点或者遍历完所有可行走区域。

ByteWhizX的博客 1273

【人工智能】在 cc-switch 中配置 AnyRouter 接入 Claude Code 完整指南

本文介绍了在cc-switch工具中配置AnyRouter中转服务以接入Claude Code的详细步骤。主要内容包括:1) 准备API令牌和端点地址;2) 填写基础信息和模型参数;3) 保存配置并重启终端生效;4) 常见问题排查方法。重点强调了API地址格式、模型ID准确性以及配置写入的必要性,帮助用户顺利完成中转服务配置,实现Claude 4.5版本的正常使用。

奶爸的编程之路,也就一周冷个三天 3102

springboot整合websocket

① 添加依赖需要ws功能的微服务模块添加XML复制代码12345<dependency> <groupId>com.pig4cloud.plugingroupId> <artifactId>websocket-spring-boot-starterartifactId>...

weixin_40764682的博客 208

总结目前开源的视频生成/视频编辑大模型

随着Sora的爆火,视频生成和视频编辑受到了越来越多的关注。这篇博客总结一下目前开源的视频生成和视频编辑的大模型,并分析他们各自的优缺点,以及在自己进行科研任务或者工作中应该如何选用对应的开源模型,希望能给从事这一领域研究和使用的小伙伴们帮助。

沉迷单车的追风少年 3541

Tomcat7.0下实现的websocket 代码

[img]http://dl.iteye.com/upload/attachment/0078/9939/7593c74a-e4a2-3d1b-974c-642455ce053e.png[/img] 测试环境: JDK1.6 Tomcat7.0.30

bdk82924 204

Hermes Agent 安装部署完全指南

Hermes Agent安装部署指南提供了两种安装方式:一键脚本安装和手动分步安装。该AI助手支持多平台运行(Linux/macOS/WSL2),核心功能仅需Git作为前置依赖,其他依赖如Python、Node.js等均由安装脚本自动处理。文档详细介绍了系统要求、依赖管理、配置目录结构、环境变量设置以及10个手动安装步骤,并提供了功能模块化选项,用户可根据需求选择安装语音交互、浏览器自动化等扩展功能。安装完成后可通过hermes doctor命令验证环境,并通过交互式向导完成初始化配置。

简简单单Onlinezuozuo 2613

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

IoT.js终极入门指南:如何在10分钟内构建你的第一个物联网应用

IoT.js是一个专为物联网设备设计的轻量级JavaScript运行时,它允许开发者使用JavaScript轻松构建物联网应用。本指南将带你快速入门IoT.js,在短短10分钟内完成从环境搭建到运行第一个物联网应用的全过程。 ## 🚀 准备工作:安装IoT.js ### 系统要求 IoT.js支持多种平台,包括Linux、NuttX、Tizen和TizenRT。作为初学者,推荐在Linux环

gitblog_00165的博客 803

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

RuView 桌面端集成化 WiFi 感知服务器:二进制捆绑、进程托管与 WebSocket 实时数据流实战解析(ADR-055)

> 本文对应 RuView 仓库中的架构决策记录 [ADR-055:Integrated Sensing Server in Desktop App](https://link.gitcode.com/i/9e66323ad64312632f29d5bf6080ddef)。该决策将原本需要独立安装、独立查找 PATH 的 `wifi-densepose-sensing-server` 感知服务器直

gitblog_00196的博客 411

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

【workerman】uniapp+thinkPHP5使用GatewayWorker实现实时通讯

合集 - JavaScript(5)1.【JavaScript】聊聊js中关于this的指向07-032.【workerman】uniapp+thinkPHP5使用GatewayWorker实现实时通讯07-053.【JavaScript】聊一聊js中的浅拷贝与深拷贝与手写实现07-134.【JavaScript】前端算法题(重建二叉树、反向输出链表每个节点)07-305.【JavaScript】...

weixin_36888774的博客 863

某东实时弹幕抓取

这次案例用的版本是9.2的,9.2以后的版本有frida检测。 1.抓包,查找sign 对于已经拿到sign只想看弹幕的部分直接跳到4。 用的抓包工具是HttpCanary,随便进入一间直播间,可以看到弹幕走的是websocket,携带的url参数token来自于下面post返回的结果,经过分析只有st,sign,sv三个参数会变,其余都不变。 既然分析完了,那就从sign开始入手。当时我找这个sign找了一会没找出来,由于sign会跟其它参数拼接成url,所以我就搜其它参.

公过水蚊的博客 3304

Pathfinder与Starknet生态集成实战:用starknet.js连接Rust全节点的完整指南

Pathfinder 是一个用 **Rust** 编写的 **Starknet 全节点**,它为开发者和用户提供了安全、完整地访问 Starknet 区块链的能力。本指南将手把手教你完成 Pathfinder 与 starknet.js、starknet.py 等主流生态工具的集成,从节点部署到 API 调用一网打尽,适合刚接触 Starknet 开发的新手快速上手。 ## 为什么你需要一个 S

gitblog_00400的博客 966

RuView WiFi-DensePose 移动伴随应用(ADR-034)架构解析:基于 Expo 的 5 屏实时 WiFi 传感 App 设计与实现

FieldView 是 RuView / WiFi-DensePose 体系的移动伴随应用(代号 **FieldView**),由 ADR-034 定义、落地于 [ui/mobile](https://link.gitcode.com/i/a1cc065fa6bcb963ac1b93aa074f2e9a),采用 Expo SDK 55 + React Native 单代码库同时产出 iOS、And

gitblog_00592的博客 342

轻量级网站AI聊天框实战:低代码、高转化、可管控

网站智能对话系统已从‘能否实现’进入‘如何高效落地’阶段。其核心是融合规则引擎与轻量RAG的分层响应机制,兼顾毫秒级确定性应答与语义理解能力;技术价值在于绕过传统客服SaaS的高成本与数据黑箱,实现知识更新即时生效、对话全程可追溯、响应延迟稳定低于800ms;典型应用于电商物流咨询、SaaS产品兼容性答疑、本地服务政策解读等高频低复杂度场景;本文聚焦中小团队可快速复用的极简路径——基于Markdown知识库、Phi-3-mini本地推理与前端Web Component嵌入,不依赖大模型API,不改动主站代码

cmff98425的博客 370

交直流混联电网潮流计算:统一迭代法的原理与Matlab实现

潮流计算是电力系统规划与运行分析的基础工具。当直流输电线路接入交流电网后,换流站引入的强非线性变量使传统牛顿-拉夫逊法难以收敛。统一迭代法将换流站方程与直流网络方程整体嵌入雅可比矩阵,实现交流变量与直流变量的联立求解,显著提升交直流混联电网潮流计算的收敛性与精度。该方法在LCC换流站建模、控制方式切换及Matlab工程实现中均有完备的数学支撑,适用于交直流混联电网规划、直流接入评估及电力系统课程设计等场景。完整算例与调试经验覆盖了从公式推导到代码实现的关键环节。

weixin_34327223的博客 377

java调用obs直播_OBS JAVA SDK Demo:设置桶策略

1背景介绍OBS桶策略可以给特定用户设置特定的权限。下面代码展示通过JAVA SDK给用户桶设置高级桶策略。2代码展示需要先下载OBS最新的JAVA SDK,参考官网链接:https://developer.huaweicloud.com/sdk?OBS,并在自己的项目中导入SDK中的JAR包。前提条件:已创建OBS桶,例如my-bucket123设置的桶策略为:给用户userB给予桶的所有权限和...

weixin_33662430的博客 2309

tomcat10 32位下载地址,windows解压版下载地址

tomcat10 32位windows解压版下载地址

资源分享免费的博客 1105
上一篇: 学习笔记052——Spring Boot 自定义 Starter
下一篇: 学习笔记054——MyBatis Plus相关笔记
须晴日.
博客等级 码龄5年 595粉丝 103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值