若依框架整合WebSocket

若依框架整合WebSocket

一、前端

1、定义socket对象

data(){
    return{
        webSocket: null,
    }
}

2、建立连接

//如果webSocket为null进行建立连接
if (!this.webSocket) {
    this.webSocket = new WebSocket(`ws://localhost:8081/handleData/`);
	
    //建立连接
    this.webSocket.onopen = function(event) {
        console.log('WebSocket connected');
    };
	
    //接收消息回调函数
    this.webSocket.onmessage = (event) => {
        // 处理从服务器接收的消息
        console.log(event)
    };
	
    //连接异常,设置webSocket对象为null
    this.webSocket.onerror = function(event) {
        console.error('WebSocket error:', event);
        this.webSocket = null;
    };
	
    //连接关闭,设置webSocket对象为null
    this.webSocket.onclose = function(event) {
        console.log('WebSocket connection closed');
        this.webSocket = null;
    };
}

3、向服务端发送消息

//如果webSocket已经建立连接,则进行数据发送
if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) {
    const msg = {
		//具体数据
    }
    this.webSocket.send(JSON.stringify(msg));
}

二、后端

1、webSocket配置

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

2、webSocket服务建立

@Slf4j
@Component
@ServerEndpoint("/handleData")  //socket连接切入点,即需要进行建立连接的url
@CrossOrigin
public class WebSocketServer {
    
    /** 日志对象 */
    private static Logger logger = LoggerFactory.getLogger(WebSocketServer.class);

    /** 记录当前在线连接数 */
    private static AtomicInteger onlineCount = new AtomicInteger(0);

    /*这是ArrayList的线程安全的版本 读多写少比较适合*/
    private static CopyOnWriteArrayList<Session> sessionList=new CopyOnWriteArrayList<>();

    /**
     * 解决无法注入bean:定义静态service对象,通过@Autowired在系统启动时为静态变量赋值
     * @ Autowired 注解作用在方法上,如果方法没有参数,spring容器会在类加载完后执行一次这个方法,
     * 如果方法中有参数的话,还会从容器中自动注入这个方法的参数,然后执行一次这个方法。
     */
    private static DataService dataService;

    @Autowired
    public void setDeviceDataService(DataService dataService) {
        WebSocketServer.dataService = dataService;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        String path = session.getRequestURI().getPath();
        //TODO:在此处获取路径里的传入参数进行建立连接
        
        onlineCount.incrementAndGet();
        sessionList.add(session);
        logger.info("socket连接加入:----deviceId: {},type: {},当前在线人数为:{}----", deviceId, type, onlineCount.get());
        
		
      	//TODO:为需要做业务处理的dataService增加会话
        MessageDto messageDto = new MessageDto();
        sessionMap.put(session,new SendDataDto(session,messageDto));
		
        //TODO:发送设备数据
        sendMessage(JSONObject.toJSONString(data), session);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        Iterator<Session> iterator = sessionList.iterator();
        while(iterator.hasNext()){
            Session next = iterator.next();
            if(session==next){
                sessionList.remove(session);
                //业务会话集合去除关闭的session
			   sessionMap.remove(session);
                onlineCount.decrementAndGet(); // 在线数减1
                logger.info("连接{}关闭",session);
            }
        }
    }
    /**
    *  连接出现异常调用的方法
    */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("系统发生错误");
	    sessionList.remove(session);
        //业务会话集合去除异常的session
        sessionMap.remove(session);
        error.printStackTrace();
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     * 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
        //服务端转发消息给所有的客户端
        MessageDto messageDto = JSONObject.parseObject(message, MessageDto.class);
        //设置节点设备信息
        for (Map.Entry<Session, SendDataDto> entry : sessionMap.entrySet()) {
            if (entry.getKey() == session) {
                MessageDto dto = entry.getValue().getMessageDto();
                //TODO:设置接收到的消息给session的MessageDto
                break;
            }
        }
        //TODO:调用业务处理的service做处理
        
        //发送数据
        sendMessage(JSONObject.toJSONString(data), session);
    }

    /**
     * 服务端发送消息给客户端
     */
    public static synchronized void sendMessage(String message, Session toSession) {
        try {
            logger.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            logger.error("服务端发送消息给客户端失败:{}",e.getMessage());
        }
    }
}

3、处理socket消息业务类

@Component
public class DataService {
    
    public static final Logger logger = LoggerFactory.getLogger(DataService.class);

    //需要业务处理的会话集合
    public static ConcurrentHashMap<Session, Object> sessionMap = new ConcurrentHashMap<>();

    @PostConstruct
    public void getAllDevicesList(){
        //TODO:业务处理需要初始化加载的数据
    }

    @Scheduled(fixedRate = 10000)
    public void fetchDataAndSendToFrontend() {
		//TODO:定时给不同的会话发送各自的消息
        for (Map.Entry<Session, Object> entry : sessionMap.entrySet()) {
            logger.info("--------------------------------------------------------------------------------");
            Object value = entry.getValue();
            
            logger.info("--------------------------------------------------------------------------------");
        }
    }

//    @Scheduled(fixedRate = 15000)
    public void getRealTimeData(){
		//业务处理
    }
}
posted @ 2024-06-05 17:25  戒爱学Java  阅读(522)  评论(0编辑  收藏  举报