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

随记:在springboot中websocket的使用

我现在有两种方法

第一种:使用java封装的这个包下的javax.websocket.*

先配置这个配置类

import com.alibaba.nacos.common.utils.CollectionUtils;
import org.springframework.stereotype.Component;import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import java.util.List;
import java.util.Map;@Component
public class WebSocketServerConfig extends ServerEndpointConfig.Configurator {@Overridepublic boolean checkOrigin(String originHeaderValue) {//todo webSocket的 过滤 权限校验return true;}@Overridepublic void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {Map<String, List<String>> parameterMap = request.getParameterMap();List<String> erpList = parameterMap.get("erp");if(!CollectionUtils.isEmpty(erpList)){sec.getUserProperties().put("erp", erpList.get(0));}}}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

 创建一个socket

前端应该怎么连接呢

 

第二种:使用spring自定义的websocket + Disruptor。

 先定义这个配置

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Resourceprivate PictureEditHandler pictureEditHandler;@Resourceprivate WsHandshakeInterceptor wsHandshakeInterceptor;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// websocketregistry.addHandler(pictureEditHandler, "/ws/picture/edit").addInterceptors(wsHandshakeInterceptor).setAllowedOrigins("*");}
}

再配置拦截器

/*** WebSocket 拦截器,建立连接前校验*/
@Slf4j
@Component
public class WsHandshakeInterceptor implements HandshakeInterceptor {@Resourceprivate UserService userService;@Resourceprivate PictureService pictureService;@Resourceprivate SpaceService spaceService;@Resourceprivate SpaceUserAuthManager spaceUserAuthManager;/*** 建立连接前要校验* @param request* @param response* @param wsHandler* @param attributes 给Session会话设置属性* @return* @throws Exception*/@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {if (request instanceof ServletServerHttpRequest) {HttpServletRequest httpServletRequest = ((ServletServerHttpRequest) request).getServletRequest();// 从请求中获取用户信息String pictureId = httpServletRequest.getParameter("pictureId");if (StrUtil.isBlank(pictureId)){log.info("缺少图片参数,拒绝握手");return false;}// 获取当前登入用户User loginUser = userService.getLoginUser(httpServletRequest);if (ObjUtil.isEmpty(loginUser)){log.info("用户未登录,拒绝握手");return false;}// 校验用户是否有编辑当前图片的权限Picture picture = pictureService.getById(pictureId);if (ObjUtil.isEmpty(picture)){log.info("图片不存在,拒绝握手");return false;}Long spaceId = picture.getSpaceId();Space space =null;if (spaceId != null){space= spaceService.getById(spaceId);if (ObjUtil.isEmpty(space)){log.info("图片所在空间不存在,拒绝握手");return false;}if (space.getSpaceType() != SpaceTypeEnum.TEAM.getValue()){log.info("图片所在空间不是团队空间,拒绝握手");return false;}}List<String> permissionList = spaceUserAuthManager.getPermissionList(space, loginUser);if (!permissionList.contains(SpaceUserPermissionConstant.PICTURE_EDIT)){log.info("用户没有编辑图片的权限,拒绝握手");return false;}// 设置用户登入信息等属性到 WebSocket 会话中attributes.put("user", loginUser);attributes.put("userId", loginUser.getId());attributes.put("pictureId", Long.valueOf(pictureId)); // 记得转换为 Long 类型}return true;}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {}
}

 再写这个disrupter的配置 这个东西就像一个工厂一样,但是不是啊。它可以根据消费者的消息类型来调用对应的方法。

/**
*disruptor 配置*/
@Configuration
public class PictureEditEventDisruptorConfig {@Resourceprivate PictureEditEventWorkHandler pictureEditEventWorkHandler;@Bean("pictureEditEventDisruptor")public Disruptor<PictureEditEvent> messageModelRingBuffer() {// ringBuffer 的大小int bufferSize = 1024 * 256;Disruptor<PictureEditEvent> disruptor = new Disruptor<>(PictureEditEvent::new,bufferSize,ThreadFactoryBuilder.create().setNamePrefix("pictureEditEventDisruptor").build());// 设置消费者disruptor.handleEventsWithWorkerPool(pictureEditEventWorkHandler);// 开启 disruptordisruptor.start();return disruptor;}
}

消费者 举的一个例子 

/*** (消费者) 这只是一个例子*/
@Slf4j
@Component
public class PictureEditEventWorkHandler implements WorkHandler<PictureEditEvent> {@Resource@Lazyprivate PictureEditHandler pictureEditHandler;@Resourceprivate UserService userService;@Overridepublic void onEvent(PictureEditEvent event) throws Exception {PictureEditRequestMessage pictureEditRequestMessage = event.getPictureEditRequestMessage();WebSocketSession session = event.getSession();User user = event.getUser();Long pictureId = event.getPictureId();// 获取到消息类别String type = pictureEditRequestMessage.getType();PictureEditMessageTypeEnum pictureEditMessageTypeEnum = PictureEditMessageTypeEnum.valueOf(type);// 调用对应的消息处理方法switch (pictureEditMessageTypeEnum) {case ENTER_EDIT:pictureEditHandler.handleEnterEditMessage(pictureEditRequestMessage, session, user, pictureId);break;case EDIT_ACTION:pictureEditHandler.handleEditActionMessage(pictureEditRequestMessage, session, user, pictureId);break;case EXIT_EDIT:pictureEditHandler.handleExitEditMessage(pictureEditRequestMessage, session, user, pictureId);break;default:PictureEditResponseMessage pictureEditResponseMessage = new PictureEditResponseMessage();pictureEditResponseMessage.setType(PictureEditMessageTypeEnum.ERROR.getValue());pictureEditResponseMessage.setMessage("消息类型错误");pictureEditResponseMessage.setUser(userService.getUserVO(user));session.sendMessage(new TextMessage(JSONUtil.toJsonStr(pictureEditResponseMessage)));}}
}

生产者的例子使用方法

/***生产者*/
@Component
@Slf4j
public class PictureEditEventProducer {@ResourceDisruptor<PictureEditEvent> pictureEditEventDisruptor;public void publishEvent(PictureEditRequestMessage pictureEditRequestMessage, WebSocketSession session, User user, Long pictureId) {RingBuffer<PictureEditEvent> ringBuffer = pictureEditEventDisruptor.getRingBuffer();// 获取可以生成的位置long next = ringBuffer.next();PictureEditEvent pictureEditEvent = ringBuffer.get(next);pictureEditEvent.setSession(session);pictureEditEvent.setPictureEditRequestMessage(pictureEditRequestMessage);pictureEditEvent.setUser(user);pictureEditEvent.setPictureId(pictureId);// 发布事件ringBuffer.publish(next);}/*** 优雅停机*/@PreDestroypublic void close() {pictureEditEventDisruptor.shutdown(); // 默认处理完全部事件,再关闭}
}

最后就是处理websocket的方法里面是发送消息的所有方法和实现,

/***  WebSocket处理器*/
@Component
public class PictureEditHandler extends TextWebSocketHandler {@Resourceprivate PictureEditEventProducer pictureEditEventProducer;
}

http://www.lryc.cn/news/572220.html

相关文章:

  • Xsens IMU与NVIDIA Jetson兼容,助您将智能和自主系统更快推向市场
  • 191. 位1的个数
  • SQL注入安全研究
  • FreeRTOS 任务管理学习笔记
  • 从代码学习深度强化学习 - Double DQN PyTorch版
  • 动态规划算法思路详解
  • uni-app总结5-UTS插件开发
  • JavaScript性能优化实战大纲
  • 介绍一款免费MES、开源MES系统、MES源码
  • Rpc - RpcCaller 模块
  • 获取gitlab上项目分支版本(二)
  • 据字典是什么?和数据库、数据仓库有什么关系?
  • 解锁 JavaScript 模块化:ES6 Module 语法深度指南
  • OpenGL——单位向量点乘和叉乘在几何的应用
  • 从C++编程入手设计模式——装饰器模式
  • implement用法
  • 客户催单-01.需求分析和设计
  • 【单片机】51单片机学习笔记
  • 数据结构 4 (栈和队列)
  • 苍穹外卖-2025 完成基础配置环节(详细图解)
  • 拼多多商家端 anti_content 补环境分析
  • 如何使用 USB 数据线将文件从 PC 传输到 iPhone
  • 【漏洞复现】Apache Kafka Connect 任意文件读取漏洞(CVE-2025-27817)
  • 数控滑台在精密制造中起着至关重要的作用
  • 主成分分析(PCA)例题——给定协方差矩阵
  • camel-ai Agent模块- CriticAgent
  • 用 python 开发一个可调用工具的 AI Agent,实现电脑配置专业评价
  • Vim:从入门到进阶的高效文本编辑器之旅
  • 微信小程序传参过来了,但是数据没有获取到
  • THUCNEWS数据集-文本分类