学习笔记,供大家参考
总结的不错的话,记得点赞收藏关注哦!
导入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();
}