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

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<>();
    
        @OnOpen
        public 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));
        }
    
        @OnClose
        public void onClose(Session session) {
            log.debug(String.format("用户:%s已断开链接"));
            webSocketMap.remove(id);
        }
    
    
        @OnError
        public void onError(Session session, Throwable error) {
            error.printStackTrace();
            log.debug("链接异常", error);
            ));
        }
    
        @OnMessage
        public 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.kler.cn/a/312996.html

相关文章:

  • Stored procedures in PostgreSQL
  • 红日靶机(七)笔记
  • 【Python】爬虫通过验证码
  • 即插即用篇 | YOLOv8 引入 代理注意力 AgentAttention
  • 【MySQL】数据库知识突破:数据类型全解析与详解
  • 【LeetCode】【算法】19. 删除链表的倒数第N个结点
  • 大模型中常见 loss 函数
  • 关于“华为杯”第二十一届中国研究生数学建模竞赛赛题下载及提交作品的重要提醒
  • pytorch实现RNN网络
  • Vue使用qrcodejs2-fix生成网页二维码
  • 解决 GitLab CI/CD 中的 `413 Request Entity Too Large` 错误
  • 生信初学者教程(五):R语言基础
  • 【计算机网络篇】电路交换,报文交换,分组交换
  • BGP实验
  • Percona发布开源DBaaS平台;阿里云RDS发布全球多活数据库(GAD);Redshift支持自然语言生成SQL
  • Pyspark dataframe基本内置方法(4)
  • 【有啥问啥】弱监督学习新突破:格灵深瞳多标签聚类辨别(Multi-Label Clustering and Discrimination, MLCD)方法
  • QT 将文字矢量化,按照设置的宽和高绘制
  • 3657A/B/AM/BM矢量网络分析仪
  • CSS - 通用左边图片,右边内容,并且控制长度溢出处理模板(vue | uniapp | 微信小程序)
  • python画图|曲线分段设置颜色基础教程
  • 什么是3D展厅?有何优势?怎么制作3D展厅?
  • 蓝星多面体foc旋钮键盘复刻问题详解
  • JVM java主流的追踪式垃圾收集器
  • docker 镜像,导入导出,
  • 【数据结构入门】排序算法之三路划分与非比较排序