JFinal整合Websocket

复制代码
学习笔记,供大家参考
总结的不错的话,记得点赞收藏关注哦!

导入JAR包 javax.websocket-api

html 复制代码
<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>

编写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);
                   }
               }

           }
       }
   }

如果是在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();

不拦截websocket的访问

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

前端js代码

java 复制代码
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();
}
相关推荐
柯南二号1 分钟前
【Java后端】Spring Boot 集成 MyBatis-Plus 全攻略
java·spring boot·mybatis
桦说编程7 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
lifallen7 小时前
Java Stream sort算子实现:SortedOps
java·开发语言
IT毕设实战小研7 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
没有bug.的程序员8 小时前
JVM 总览与运行原理:深入Java虚拟机的核心引擎
java·jvm·python·虚拟机
甄超锋8 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
阿华的代码王国9 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Zyy~9 小时前
《设计模式》装饰模式
java·设计模式
A尘埃9 小时前
企业级Java项目和大模型结合场景(智能客服系统:电商、金融、政务、企业)
java·金融·政务·智能客服系统
青云交9 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市交通拥堵治理与出行效率提升中的应用(398)
java·大数据·flink·大数据可视化·拥堵预测·城市交通治理·实时热力图