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

springboot创建websocket服务端

springboot创建websocket服务端

1.配置类

package com.neusoft.airport.websocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;import java.text.SimpleDateFormat;
import java.util.Date;/*** @author dume* @create 2023-07-24 17:11**/
@Configuration
//@ConditionalOnWebApplication
public class WebSocketConfig {/*** ServerEndpointExporter 作用** 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint** @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}/*** 通信文本消息和二进制缓存区大小* 避免对接 第三方 报文过大时,Websocket 1009 错误* @return*/@Beanpublic ServletServerContainerFactoryBean createWebSocketContainer() {ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();// 在此处设置bufferSizecontainer.setMaxTextMessageBufferSize(10240000);container.setMaxBinaryMessageBufferSize(10240000);container.setMaxSessionIdleTimeout(15 * 60000L);return container;}}

2.通讯类server

package com.neusoft.airport.websocket;import com.alibaba.fastjson.JSONObject;import com.neusoft.caeid.upms.license.LicenseSetting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.PongMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** @author dume* @create 2023-07-24 17:11**/@Component
@ServerEndpoint("/webSocket/{sid}")
public class WebSocketServer implements EnvironmentAware {private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。private static int onlineCount = 0;//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();private ScheduledExecutorService executor= Executors.newSingleThreadScheduledExecutor();private static Environment globalEnvironment;//接收sidprivate String sid="";//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;@Autowiredprivate Environment environment;/*** 连接建立成功调用的方法** @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据*/@OnOpenpublic void onOpen(Session session,@PathParam("sid") String sid) throws IOException {//防止重复连接for (WebSocketServer item : webSocketSet) {if (item.sid.equals(sid)) {webSocketSet.remove(item);subOnlineCount();           //在线数减1break;}}this.session = session;this.environment = globalEnvironment;webSocketSet.add(this);     //加入set中addOnlineCount();           //在线数加1log.info("有新用户连接,连接名:"+sid+",当前在线人数为" + getOnlineCount());this.session.getAsyncRemote().sendPing(ByteBuffer.wrap(new byte[0]));this.sid=sid;}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {webSocketSet.remove(this);  //从set中删除subOnlineCount();           //在线数减1log.info("连接关闭:"+sid+"当前在线人数为" + getOnlineCount());}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息* @param session 可选的参数*/@OnMessagepublic void onMessage(String message, Session session) {log.info("收到来自:"+sid+"的信息:"+message);
//        //群发消息for (WebSocketServer item : webSocketSet) {try {LicenseSetting.CheckParams checkParams = LicenseSetting.getCheckParams();//当前license信息log.info("当前证书信息: "+ JSONObject.toJSONString(checkParams));if(null!=checkParams.getLicenseParams()){checkParams.getLicenseParams().setSysMessageInfo(null);}String sendMessageStr = JSONObject.toJSONString(checkParams);if(checkParams.getStatus()==0){log.info("证书验证成功!");}else {log.error("证书验证失败!");}item.sendMessage(sendMessageStr);} catch (IOException e) {log.error("推送消息到:"+sid+",推送内容出错",e);continue;}}}/*** 发生错误时调用*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("发生错误",error);}// 接收心跳消息@OnMessagepublic void onPong(PongMessage pong, Session session, @PathParam("sid") String sid) {executor.schedule(() -> {try {// 发送空的Ping消息session.getAsyncRemote().sendPing(ByteBuffer.wrap(new byte[0]));} catch (IOException e) {// 处理发送失败的情况log.error("Ping 用户:{} 心跳异常,关闭会话,错误原因:{}", sid, e.getMessage());onClose();}}, 10, TimeUnit.SECONDS);}/*** 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。*/public void sendMessage(String message) throws IOException {//this.session.getBasicRemote().sendText(message);this.session.getAsyncRemote().sendText(message);}/*** 群发自定义消息* */public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {//log.info("推送消息到窗口"+sid+",推送内容:"+message);for (WebSocketServer item : webSocketSet) {try {log.info("推送消息到:"+item.sid+",推送内容:"+message);//这里可以设定只推送给这个sid的,为null则全部推送if(sid==null||sid.length()==0) {item.sendMessage(message);}else if(item.sid.equals(sid)){item.sendMessage(message);}} catch (IOException e) {log.error("发生错误",e);continue;}}}//推送给指定sidpublic static boolean sendInfoBySid(@PathParam("sid") String sid,String message) throws IOException {//log.info("推送消息到窗口"+sid+",推送内容:"+message);boolean result=false;if(webSocketSet.size()==0){result=false;}for (WebSocketServer item : webSocketSet) {try {if(item.sid.equals(sid)){item.sendMessage(message);log.info("推送消息到:"+sid+",推送内容:"+message);result=true;}} catch (IOException e) {log.error("发生错误",e);continue;}}return result;}public static synchronized int getOnlineCount() {return onlineCount;}public static synchronized void addOnlineCount() {WebSocketServer.onlineCount++;}public static synchronized void subOnlineCount() {if(WebSocketServer.onlineCount>0){WebSocketServer.onlineCount--;}}@Overridepublic void setEnvironment(final Environment environment) {this.environment = environment;if (globalEnvironment == null && environment != null) {globalEnvironment = environment;}}
}
http://www.lryc.cn/news/124641.html

相关文章:

  • 网络安全攻防实战:探索互联网发展史
  • pwm接喇叭搞整点报时[keyestudio的8002模块]
  • 配置listener tcps加密 enable SSL encryption for Oracle SQL*Net
  • 【Sklearn】基于逻辑回归算法的数据分类预测(Excel可直接替换数据)
  • 自然数的拆分问题
  • du -mh命令
  • MySQL 8 group by 报错 this is incompatible with sql_mode=only_full_group_by
  • Mongodb (四十一)
  • 16 dlsys GAN
  • css3-flex布局:基础使用 / Flexbox布局
  • MYSQL-习题掌握
  • Python-迭代
  • 【论文阅读】DEPCOMM:用于攻击调查的系统审核日志的图摘要(SP-2022)
  • 大语言模型之一 Attention is all you need ---Transformer
  • 数字鸿沟,让气候脆弱者更脆弱
  • Tomcat 部署优化
  • Django框架-使用celery(一):django使用celery的通用配置,不受版本影响
  • nvue语法与vue的部分区别
  • Java 开发工具 IntelliJ IDEA
  • 将vsCode 打开的多个文件分行(栏)排列,实现全部显示,便于切换文件
  • java中的同步工具类CountDownLatch
  • 路由器和交换机的区别
  • FreeRTOS(动态内存管理)
  • IntelliJ IDEA(简称Idea) 基本常用设置及Maven部署---详细介绍
  • 【LeetCode每日一题】——128.最长连续序列
  • Redis_缓存1_缓存类型
  • 模拟 枚举
  • 【实操】2023年npm组件库的创建发布流程
  • 缓存设计的典型方案
  • SQL笔记