一、 pom依赖
springboot版本
<!-- websocket dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.7.12</version>
</dependency>
二、3个工具类拿来就用
①WebSocketConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* WebSocket配置类。开启WebSocket的支持
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
②WebsocketService
import ***.alibaba.fastjson.JSONObject;
import ***.xiaoqiu.juyilargescreen.utils.WebsocketServiceResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.***ponent;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
*/
@ServerEndpoint("/notice/{userId}")
@***ponent
@Slf4j
public class WebsocketService {
//记录连接的客户端
public static Map<String, Session> clients = new ConcurrentHashMap<>();
/**
* userId关联sid(解决同一用户id,在多个web端连接的问题)
*/
public static Map<String, Set<String>> conns = new ConcurrentHashMap<>();
private String sid = null;
private String userId;
private static Map map = new HashMap();
/**
* 连接成功后调用的方法
* @param session
* @param userId
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
this.sid = UUID.randomUUID().toString();
this.userId = userId;
clients.put(this.sid, session);
Set<String> clientSet = conns.get(userId);
if (clientSet==null){
clientSet = new HashSet<>();
conns.put(userId,clientSet);
}
clientSet.add(this.sid);
log.info(this.sid + "连接开启!");
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
log.info(this.sid + "连接断开!");
clients.remove(this.sid);
}
/**
* 判断是否连接的方法
* @return
*/
public static boolean isServerClose() {
if (WebsocketService.clients.values().size() == 0) {
log.info("已断开");
return true;
}else {
log.info("已连接");
return false;
}
}
/**
* 发送给所有用户
* @param noticeType
*/
public static void sendMessage(String noticeType){
WebsocketServiceResp WebsocketServiceResp = new WebsocketServiceResp();
WebsocketServiceResp.setNoticeType(noticeType);
sendMessage(WebsocketServiceResp);
}
/**
* 发送给所有用户
* @param WebsocketServiceResp
*/
public static void sendMessage(WebsocketServiceResp WebsocketServiceResp){
String message = JSONObject.toJSONString(WebsocketServiceResp);
for (Session session1 : WebsocketService.clients.values()) {
try {
session1.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 收到客户端消息后调用的方法
* @param message
* @param session
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("收到来自窗口"+this.userId+"的信息:"+message);
}
/**
* 发生错误时的回调函数
* @param error
*/
@OnError
public void onError(Throwable error) {
log.info("错误");
error.printStackTrace();
}
}
③WebsocketServiceResp
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("ws通知返回对象")
public class WebsocketServiceResp<T> {
@ApiModelProperty(value = "通知类型")
private String noticeType;
@ApiModelProperty(value = "通知内容")
private T noticeInfo;
}
三、controller监测接口是否被调用,并给前端推送消息
@ApiOperation("修改名称的接口")
@GetMapping("/edit")
//必须加,否则容易报错
@ResponseBody
public boolean edit(Integer id, String name) {
//通知前端修改了数据(前端收到结果,会重新调用获取数据列表的接口)
WebsocketService.sendMessage("调用了修改名称");
//修改的操作(这里是简单示例,看个人需求)
Goods goods = goodsService.getById(id);
goods.setGoodName(name);
//返回修改结果 true或false
return goodsService.updateById(goods);
}
四、最终效果
启动后
前端收到推送消息,重新获取数据列表接口(前端操作,这里不多写)