当前位置: 首页 > news >正文

JFinal整合Websocket

学习笔记,供大家参考
总结的不错的话,记得点赞收藏关注哦!
  1. 导入JAR包 javax.websocket-api

    <dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1</version><scope>provided</scope>
    </dependency>
    
  2. 编写WebSocket.class

    package cn.bigchin.spark.app.ws;import cn.bigchin.spark.Spark;
    import cn.bigchin.spark.SparkConst;
    import cn.bigchin.spark.expand.event.SparkEvent;
    import com.jfinal.kit.Kv;
    import com.jfinal.kit.StrKit;
    import com.jfinal.log.Log;
    import javax.websocket.*;
    import javax.websocket.Session;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;import java.io.IOException;
    import java.util.concurrent.ConcurrentSkipListMap;/*** TODO:** @author 一川死水 (yichuan95@126.com)* @Date 2024/9/19*/
    @ServerEndpoint("/websocket/{id}")
    public class WebSocket {Log log = Log.getLog(WebSocket.class);private String id;//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;//concurrent包的线程安全Set,用来存储每个客户端对应的MySocket对象private static ConcurrentSkipListMap<String, WebSocket> webSocketMap = new ConcurrentSkipListMap<>();@OnOpenpublic void onOpen(@PathParam("id") String id, Session session) throws IOException {this.session = session;this.id = id;webSocketMap.put(id, this);log.debug(String.format("用户:%s已连接", id));}@OnClosepublic void onClose(Session session) {log.debug(String.format("用户:%s已断开链接"));webSocketMap.remove(id);}@OnErrorpublic void onError(Session session, Throwable error) {error.printStackTrace();log.debug("链接异常", error);));}@OnMessagepublic void onMessage(Session session, String message) throws IOException {// 收到消息,根据自己的业务作实际处理判断是否在线,如原样发送回客户端session.getBasicRemote().sendText(message);}/*** TODO:群发自定义消息(建议使用此方法)** @param id      用户id id为null时 ,为群发* @param message 消息内容*/public static void sendMessage(String id, String message) throws IOException {for (String idKey : webSocketMap.keySet()) {if (StrKit.isBlank(id)) {webSocketMap.get(idKey).session.getAsyncRemote().sendText(message);} else {if (idKey.equals(id)) {webSocketMap.get(idKey).session.getAsyncRemote().sendText(message);}}}}
    }
    
  3. 如果是在undertow 下启动,则要继续添加依赖,如果是tomcat环境下,可跳过这一步

     <!-- jfinal-undertow  --><dependency><groupId>com.jfinal</groupId><artifactId>jfinal-undertow</artifactId><version>2.0</version></dependency><!-- 开发 WebSockets 时开启下面的依赖 --><dependency><groupId>io.undertow</groupId><artifactId>undertow-websockets-jsr</artifactId><version>2.0.28.Final</version></dependency>
    

    然后在undertow启动添加websocket集成

     //configClass自行替换成自己的配置类UndertowServer server = UndertowServer.create(configClass);server.configWeb(webBuilder -> {webBuilder.addWebSocketEndpoint(WebSocket.class);});server.start();
    
  4. 不拦截websocket的访问

    //在自己的配置类中添加拦截,
    //如果WebSocket 中的@ServerEndpoint配置地址有带.的,如@ServerEndpoint("/websocket.ws/{id}"),则无需添加拦截,因为带 "." 字符的 url 不会被 jfinal 框架当成 action,所以直接跳过了
    public void configHandler(Handlers me) {me.add(new UrlSkipHandler("^/websocket", false));
    }
    
  5. 前端js代码

    let id='1'
    let webSocket = null;
    if (window.WebSocket) {if(Protocol == 'https'){websocket = new WebSocket('wss://' + host + '/websocket/' + id);}else{websocket = new WebSocket('ws://' + host + '/websocket/' + id);}      
    } else {   console.log("您的浏览器不支持WebSocket");return;
    }
    //打开事件
    webSocket.onopen = function (){console.log("WebSocket已打开");//webSocket.send("这是来自客户端的消息"+id+new Date());
    }
    //获得消息事件
    webSocket.onmessage = function (message){//收到消息,自行处理业务逻辑console.log(message)
    }
    //关闭事件
    webSocket.onclose = function (){console.log("Socket已关闭");
    }
    //发生了错误
    webSocket.onerror = function (){console.log("Socket发生了错误");
    }
    //发送消息
    function send(message) {websocket.send(message);
    }
    //当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口
    window.onbeforeunload = function () {websocket.close();
    }
    
http://www.lryc.cn/news/446815.html

相关文章:

  • (done) 声音信号处理基础知识(7) (Understanding Time Domain Audio Features)
  • 拓数派荣获上海数据交易所“数据治理服务商”认证
  • 【Redis】分布式锁之 Redission
  • 对象序列化
  • 什么是专利开放许可?
  • 地表最强开源大模型!Llama 3.2,如何让你的手机变身私人智能助理
  • Pandas中DataFrame表格型数据结构
  • C++的智能指针
  • 微信小程序showLoading ,showToast ,hideLoading连续调用出现showLoading 不关闭的情况记录
  • OpenFeign使用详解
  • CSS clip-path 属性的使用
  • PHP 函数
  • NCEloss与InfoNCEloss的区别
  • 高通Android 12 push framework.jar和service.jar
  • HTTPS证书配置
  • Image matting入门
  • 基于安全风险预测的自动驾驶自适应巡航控制优化
  • Docker Compose 搭建 Redis 哨兵集群模式搭建详解(1主2从+3哨兵)(包含主从复制的搭建) (保证一遍学会)
  • Oracle 单机和集群环境部署教程
  • springboot 整合酷狗获取MV视频最高画质(使用自己账户)
  • 数字孪生平台,助力制造设备迈入超感知与智控新时代!
  • 音视频入门基础:AAC专题(10)——FFmpeg源码中计算AAC裸流每个packet的pts、dts、pts_time、dts_time的实现
  • pycirclize python包画circos环形图
  • Redis Sorted Set 跳表的实现原理和分析
  • 新手教学系列——在MySQL分表中批量调整表结构的实践与优化
  • 解决事务提交延迟问题:Spring中的事务绑定事件监听机制解析
  • Python 异步编程的秘密武器:Asyncio
  • 10年计算机考研408-计算机网络
  • 深信服校招面试总结
  • 【LeetCode热题100】模拟