【Java后端向前端推送消息】

【Java后端向前端推送消息】

1、WebSocketConfig配置类

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration @EnableWebSocket publicclassWebSocketConfig{ @Bean public ServerEndpointExporter serverEndpointExporter(){returnnewServerEndpointExporter();}}

2、WebSocket消息发送接收

import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component;import org.springframework.util.ObjectUtils;import javax.websocket.*;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint;import java.util.Map;import java.util.Set;import java.util.concurrent.ConcurrentHashMap; @Slf4j @Component @ServerEndpoint(value ="/web/{id}")publicclassWebSocketProcess{/* * 持有每个webSocket对象,以key-value存储到线程安全ConcurrentHashMap, */privatestatic ConcurrentHashMap<Long, WebSocketProcess> concurrentHashMap =newConcurrentHashMap<>(12);/** * 会话对象 **/private Session session;/* * 客户端创建连接时触发 * */ @OnOpen publicvoidonOpen(Session session, @PathParam("id") long id){//每新建立一个连接,就把当前客户id为key,this为value存储到map中this.session = session; concurrentHashMap.put(id,this); log.info("Open a websocket. id={}", id);}/** * 客户端连接关闭时触发 **/ @OnClose publicvoidonClose(Session session, @PathParam("id") long id){//客户端连接关闭时,移除map中存储的键值对 concurrentHashMap.remove(id); log.info("close a websocket, concurrentHashMap remove sessionId= {}", id);}/** * 接收到客户端消息时触发 */ @OnMessage publicvoidonMessage(String message, @PathParam("id") String id){ log.info("receive a message from client id={},msg={}", id, message);}/** * 连接发生异常时候触发 */ @OnError publicvoidonError(Session session, Throwable error){ log.error("Error while websocket. ", error);}/** * 发送消息到指定客户端 * * @param id * @param message */publicvoidsendMessage(long id, String message) throws Exception {//根据id,从map中获取存储的webSocket对象 WebSocketProcess webSocketProcess = concurrentHashMap.get(id);if(!ObjectUtils.isEmpty(webSocketProcess)){//当客户端是Open状态时,才能发送消息if(webSocketProcess.session.isOpen()){ webSocketProcess.session.getBasicRemote().sendText(message);}else{ log.error("websocket session={} is closed ", id);}}else{ log.error("websocket session={} is not exit ", id);}}/** * 发送消息到所有客户端 */publicvoidsendAllMessage(String msg) throws Exception { log.info("online client count={}", concurrentHashMap.size()); Set<Map.Entry<Long, WebSocketProcess>> entries = concurrentHashMap.entrySet();for(Map.Entry<Long, WebSocketProcess> entry : entries){ Long cid = entry.getKey(); WebSocketProcess webSocketProcess = entry.getValue(); boolean sessionOpen = webSocketProcess.session.isOpen();if(sessionOpen){ webSocketProcess.session.getBasicRemote().sendText(msg);}else{ log.info("cid={} is closed,ignore send text", cid);}}}}

3、消息推送Controller

import com.xyl.web.controller.common.WebSocketProcess;import com.xyl.web.controller.common.WebSocketServer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/testws")publicclassWebSocketController{/** * 注入WebSocketProcess **/ @Autowired private WebSocketProcess webSocketProcess;/** * 向指定客户端发消息 * * @param id */ @PostMapping(value ="sendMsgToClientById")publicvoidsendMsgToClientById(@RequestParam long id, @RequestParam String text){try{ webSocketProcess.sendMessage(id, text);}catch(Exception e){ e.printStackTrace();}}/** * 发消息到所有客户端 * * @param text */ @PostMapping(value ="sendMsgToAllClient")publicvoidsendMsgToAllClient(@RequestParam String text){try{ webSocketProcess.sendAllMessage(text);}catch(Exception e){ e.printStackTrace();}}/** * 定时向客户端推送消息 * @throws Exception */ @Scheduled(cron ="0/5 * * * * ?")privatevoidconfigureTasks() throws Exception { webSocketProcess.sendAllMessage("向前端推送消息内容");}}

4、测试HTML

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>websocket测试</title><script src="http://code.jquery.com/jquery-2.1.1.min.js"></script></head><body><div id="content"></div></body><script type="text/javascript">$(function(){var ws;//检测浏览器是否支持webSocketif("WebSocket"in window){$("#content").html("您的浏览器支持webSocket!");//模拟产生clientIDlet clientID = Math.ceil(Math.random()*100);//创建 WebSocket 对象,注意请求路径!!!! ws =newWebSocket("ws://127.0.0.1:9095/web/"+clientID);//与服务端建立连接时触发 ws.onopen=function(){$("#content").append("<p>与服务端建立连接建立成功!您的客户端ID="+clientID+"</p>");//模拟发送数据到服务器 ws.send("你好服务端!我是客户端 "+clientID);}//接收到服务端消息时触发 ws.onmessage=function(evt){let received_msg = evt.data;$("#content").append("<p>接收到服务端消息:"+received_msg+"</p>");};//服务端关闭连接时触发 ws.onclose=function(){ console.error("连接已经关闭.....")};}else{$("#content").html("您的浏览器不支持webSocket!");}})</script></html>

Read more

微信终于开放官方 Bot API!ClawBot 插件深度解析,AI 开发者的新机遇

微信终于开放官方 Bot API!ClawBot 插件深度解析,AI 开发者的新机遇

⚡⚡⚡ 欢迎预览,批评指正⚡⚡⚡ 文章目录 * 一、历史性时刻:微信开放官方 Bot API * 二、插件概况:什么是 ClawBot? * 2.1 官方定位 * 2.2 核心能力 * 三、技术亮点:iLink 协议深度解析 * 3.1 协议概览 * 3.2 认证机制 * 3.3 长轮询机制 * 3.4 消息结构 * 3.5 回复机制(关键!) * 3.6 CDN 媒体加密 * 四、启用插件:5 分钟快速上手 * 4.1 前置条件 * 4.

Whisper语音识别案例:语音博客内容索引

Whisper语音识别案例:语音博客内容索引 1. 引言 随着多语言内容创作的快速增长,如何高效地对音频内容进行索引、检索和再利用成为技术团队面临的重要挑战。传统的语音识别方案往往受限于语言支持范围、准确率和部署复杂度,难以满足全球化内容生产的需求。基于 OpenAI Whisper Large v3 模型构建的语音识别 Web 服务,为这一问题提供了高精度、多语言、易部署的解决方案。 本项目由 by113 小贝二次开发,聚焦于将 Whisper 的强大能力应用于实际场景——特别是语音博客的内容自动化处理。通过集成 Gradio 构建交互式界面,结合 FFmpeg 实现音频预处理,并利用 CUDA 加速推理过程,该系统实现了对 99 种语言的自动检测与高精度转录,显著提升了语音内容的可读性与可搜索性。 本文将深入解析该系统的架构设计、关键技术实现路径以及工程落地中的优化策略,帮助开发者快速掌握基于 Whisper 构建语音识别服务的核心方法。 2. 系统架构与技术选型 2.1

VibeVoice与Whisper组合:构建完整语音双工交互系统

VibeVoice与Whisper组合:构建完整语音双工交互系统 1. 为什么需要真正的语音双工系统? 你有没有试过和智能助手对话时,得等它说完才能开口?或者刚说到一半,它就急着插话打断?这不是体验问题,而是技术断层——大多数语音系统把“听”和“说”当成两件孤立的事。 真正的语音双工(Full-Duplex)不是简单地把TTS和ASR拼在一起。它要求系统能同时听、实时理解、即时响应,并且说话时不卡顿、不抢话、不漏听。就像两个人自然交谈那样:你开口时我听着,你一停我就接上,中间没有沉默空档,也没有机械等待。 VibeVoice + Whisper 的组合,第一次让这个目标在单机部署环境下变得触手可及。它不依赖云端API,不牺牲隐私,也不需要定制硬件——一台带RTX 4090的服务器就能跑起来,而且从输入文字到语音输出只要300毫秒,从麦克风收音到文字返回不到800毫秒。 这篇文章不讲理论推导,不堆参数对比,只带你一步步搭出一个真正能“对话”的本地语音系统:能边听边想、边说边听、流式响应、中文界面、开箱即用。

Cogito-v1-preview-llama-3B开源优势解析:商业可用+开放许可+可自主部署

Cogito-v1-preview-llama-3B开源优势解析:商业可用+开放许可+可自主部署 1. 为什么Cogito-v1-preview-llama-3B值得关注 如果你正在寻找一个既强大又实用的开源语言模型,Cogito-v1-preview-llama-3B绝对值得你深入了解。这个模型来自Deep Cogito团队,是他们混合推理模型系列的首个预览版本。 最吸引人的是,这个模型在保持3B参数轻量级的同时,在大多数标准基准测试中都超越了同等规模的其他开源模型。这意味着你不需要庞大的计算资源,就能获得相当不错的性能表现。 更重要的是,Cogito-v1-preview-llama-3B采用完全开放的许可协议,允许商业使用。这对于想要将AI能力集成到商业产品中的开发者和企业来说,是个难得的好消息。 2. 核心特性与技术创新 2.1 混合推理架构 Cogito模型的最大亮点是其混合推理能力。它可以在两种模式下工作: * 标准模式:像传统语言模型一样直接回答问题 * 推理模式:在回答前进行自我反思和思考,类似于人类的推理过程 这种设计让模型既能快速响应简单问