【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

解析 ‘LLM-as-a-judge’:如何编写一套可靠的 Prompt 让 GPT-4 为你的 Llama-3 输出打分?

各位编程爱好者、AI工程师们: 大家好!欢迎来到今天的技术讲座。今天,我们将深入探讨一个在当前AI领域备受关注且极具实用价值的话题:如何利用“LLM-as-a-judge”范式,特别是如何编写一套可靠的Prompt,让强大的GPT-4模型为我们的Llama-3模型输出进行打分和评估。 随着大语言模型(LLM)技术的飞速发展,我们拥有了Llama-3、GPT-4等一系列令人惊叹的模型。但随之而来的挑战是:我们如何有效地评估这些模型的性能?特别是在微调(fine-tuning)、Prompt工程优化,甚至是模型架构迭代的过程中,我们需要一个快速、可扩展且尽可能客观的评估机制。传统的基于人工标注的评估方式,虽然“金标准”性强,但成本高昂、耗时费力,难以跟上模型迭代的速度。 正是在这样的背景下,“LLM-as-a-judge”应运而生。它利用一个或多个强大的LLM(通常是能力更强的模型,如GPT-4)来评估另一个LLM(例如我们的Llama-3)的输出质量。这种方法不仅可以大幅提升评估效率,还能在一定程度上自动化评估流程,为我们的模型开发提供快速反馈。 今天的讲座,我将作为一名编程专家

Python AI入门:从Hello World到图像分类

Python AI入门:从Hello World到图像分类 一、Python AI的Hello World 1.1 环境搭建 首先,我们需要搭建Python AI的开发环境: # 安装PyTorch pip install torch torchvision # 安装其他依赖 pip install numpy matplotlib 1.2 第一个AI程序 让我们来编写一个最简单的AI程序 - 线性回归: import torch import torch.nn as nn import numpy as np import matplotlib.pyplot as plt # 生成训练数据 x = torch.linspace(

使用 VS Code 和 Android Studio 阅读 Android 源码:基于 Copilot 的高效代码分析技巧

使用 VS Code 和 Android Studio 阅读 Android 源码:基于 Copilot 的高效代码分析技巧

1. 背景 在日常开发中,大家常用 AI 工具(如 ChatGPT、DeepSeek 等)进行代码分析。但通过网页 AI 工具分析代码时,缺乏上下文,需要手动分段粘贴代码,效率低且容易遗漏关键信息。 公司引入 Copilot 后,大家多在 VS Code、Android Studio 等 IDE 插件中用 Copilot 进行代码分析。Copilot 能直接分析当前编辑器中的代码,并支持上下文,极大提升了分析效率,减少了人工粘贴的麻烦。 但实际开发中,仍存在以下痛点: * 代码跳转不连贯:对于 Android.bp soong 构建系统下的 Android 代码,不能自由地跳转到方法定义、实现、符号等。 * 查找方法繁琐:大部分

Qwen3-1.7B代码生成效果如何?GitHub Copilot类比评测

Qwen3-1.7B代码生成效果如何?GitHub Copilot类比评测 最近,阿里开源了新一代的千问大模型系列——Qwen3。这个系列阵容强大,从0.6B到235B,各种尺寸都有。今天,咱们不聊那些动辄几百亿参数的大块头,就聚焦一个特别有意思的小家伙:Qwen3-1.7B。 为什么是它?因为1.7B这个参数量,刚好卡在一个很微妙的位置:它比那些动辄几十亿参数的“大模型”轻巧得多,理论上部署和推理成本都更低;但又比一些纯玩具级别的微型模型要“聪明”不少。更重要的是,它主打的就是代码生成能力。 这让我立刻想到了一个“参照物”——GitHub Copilot。作为目前最流行的AI编程助手,Copilot几乎成了代码生成的代名词。那么,这个新来的、开源的、只有1.7B参数的Qwen3,在代码生成这件事上,到底有几斤几两?它能达到Copilot几成的功力?还是说,它有自己的独特优势? 这篇文章,我就带你一起上手实测,用最直观的方式,看看Qwen3-1.7B在代码生成上的真实表现,