一、 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的支持 */@Configurationpublic class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }}
②WebsocketService
import com.alibaba.fastjson.JSONObject;import com.xiaoqiu.juyilargescreen.utils.WebsocketServiceResp;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component;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}")@Component@Slf4jpublic 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); }
四、最终效果
启动后
前端收到推送消息,重新获取数据列表接口(前端操作,这里不多写)