1、新建WebSocketConfig配置类

package com.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

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

2、新建具体业务socket

package com.socket;

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.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@ServerEndpoint("/sysMessageSocket/{token}")
@Component
@Slf4j
public class SysMessageWebSocket {
    private Session session;
    private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();
    private static CopyOnWriteArraySet<SysMessageWebSocket> webSocketSet = new CopyOnWriteArraySet<>();

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "token") String token) {
        log.info("WebSocket建立连接中,连接用户ID:{}", token);
        try {
            Session historySession = sessionPool.get(token);
            if (historySession != null) {
                webSocketSet.remove(historySession);
                historySession.close();
            }
        } catch (IOException e) {
            log.error("重复登录异常,错误信息:" + e.getMessage(), e);
        }
        this.session = session;
        webSocketSet.add(this);
        sessionPool.put(token, session);
        log.info("建立连接完成,当前在线人数为:{}", webSocketSet.size());
    }

    @OnError
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }

    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        String token = this.session.getRequestParameterMap().get("token").get(0);
        log.info(token + "连接断开,当前在线人数为:{}", webSocketSet.size());
    }

    @OnMessage
    public void onMessage(String message) {
        log.info("收到客户端发来的消息:{}", message);
    }

    public void sendMessageByUser(String token, String message) {
        log.info("用户ID:" + token + ",推送内容:" + message);
        Session session = sessionPool.get(token);
        try {
            if(session!=null){
                session.getBasicRemote().sendText(message);
            }else{
                log.info("连接已断开,用户ID:" + token + ",内容推送失败:" + message + "。session为空。");
            }
        } catch (IllegalStateException | IOException e) {
            log.info("连接已断开,用户ID:" + token + ",内容推送失败:" + message + "。"+e.getMessage());
        }
    }

    public void sendAllMessage(String message) {
        log.info("发送消息:{}", message);
        for (SysMessageWebSocket webSocket : webSocketSet) {
            try {
                webSocket.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                log.error("群发消息发生错误:" + e.getMessage(), e);
            }
        }
    }

}

3、测试

通过 www.jsons.cn/websocket/ 测试本地socket是否互通

注意:

config配置文件WebSocketConfig的ServerEndpointExporter(服务器端点导出器)与@Test冲突(websocket是需要依赖tomcat等容器的启动)

方案:本地启用测试代码时需要将@Bean注掉(提交git的代码需要将Test代码注掉);

  新建测试类时,在springbootTest后添加内容webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT。

例如测试类为

package com.test;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MicroenterpriseApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class VerifyCodeServiceImplTest {

    @Test
    public void getVerifyCode() {
        
    }
}

 

posted on 2023-02-01 16:03  程序员丁先生  阅读(170)  评论(0编辑  收藏  举报