springboot Socket 通信

一、引入依赖:
  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
<!--            <version>2.7.1</version>-->
        </dependency>
二、准备工具类:
/**
 * @author WeiDaPang
 */
@Configuration
public class ScheduledConfiguration{
    @Bean
    public TaskScheduler taskScheduler(){
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        taskScheduler.initialize();
        return taskScheduler;
    }
}
/**
 * WebSocket 配置
 * @author WeiDaPang
 */
@EnableWebSocket
@Configuration
public class WebSocketConfig implements WebSocketConfigurer {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }

    /**
     *  注入WebSocket的处理器
     */
    @Resource
    private WebSocketServer  webSocketServer;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // webSocketDemo 为前端请求的地址,前端具体地址组成结构为:ws://ip:接口启动的端口/webSocketDemo
        registry.addHandler(webSocketServer,"webSocketByNotice")
                .setAllowedOrigins("*");
    }
}
/**
 * @author Da.Pang
 * 2022/11/8 18:57
 */
public class WebSocketEntity {

    private String userId;
    private WebSocketSession webSocketSession;

    public WebSocketEntity(String userId , WebSocketSession webSocketSession){
        this.userId = userId;
        this.webSocketSession = webSocketSession;
    }

    public String getUserId() {
        return userId;
    }

    public WebSocketEntity setUserId(String userId) {
        this.userId = userId;
        return this;
    }

    public WebSocketSession getWebSocketSession() {
        return webSocketSession;
    }

    public WebSocketEntity setWebSocketSession(WebSocketSession webSocketSession) {
        this.webSocketSession = webSocketSession;
        return this;
    }
}
/**
 * @author WeiDaPang
 */
@Component
public class WebSocketServer extends AbstractWebSocketHandler {

    private static final Logger logger = LoggerFactory.getLogger(WsService.class);

    @Resource
    private WsService  wsService;

    /**
     * 连接成功后触发
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        logger.info("...[客户端连接成功]...");
        // 客户端建立连接,将客户端的session对象加入到WebSocketSessionManager的sessionGroup中
        WebSocketSessionManager.add(session);
        //将连接结果返回给客户端
        wsService.sendMsg(session,session.getId()+" 连接成功"+ LocalDateTime.now());
    }

    /**
     * 关闭socket连接后触发
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        logger.info("...【客户端关闭连接成功】...");
        // 关闭连接,从WebSocketSessionManager的sessionGroup中移除连接对象
        WebSocketSessionManager.removeAndClose(session);
    }

    /**
     * 接收客户端发送的文本消息
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        logger.info("{ 客户端发送:}"+message.getPayload());
        //将连接结果返回给客户端
        wsService.sendMsg(session,message.getPayload());
    }

    /**
     * 接收客户端发送的二进制消息
     */
    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
        logger.info("{ 客户端二进制发送: }"+message.getPayload());
    }

    /**
     * 异常处理
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println();
        logger.error("*** socket异常: "+exception.getMessage(),exception);
        // 出现异常则关闭连接,从WebSocketSessionManager的sessionGroup中移除连接对象
        WebSocketSessionManager.removeAndClose(session);
    }
}
/**
 * @author WeiDaPang
 */
public class WebSocketSessionManager {
    private static final Logger logger = LoggerFactory.getLogger(WebSocketSessionManager.class);
    /**
     * 保存连接对象的 session 到集合中
     */
    public  static ConcurrentHashMap<String, WebSocketEntity> sessionGroup = new ConcurrentHashMap<>();


    /**
     * 添加 session 到集合中
     * @param session 连接对象的session
     */
    public static void add(WebSocketSession session) {
        logger.info(String.valueOf(session.getUri()));
        sessionGroup.put(session.getId(), new WebSocketEntity(getUserIdBySession(session), session));
    }

    /**
     * 从集合中删除 session,会返回删除的 session
     * @param key 通过session.getId()得到
     */
    public static WebSocketSession remove(String key) {
        return sessionGroup.remove(key).getWebSocketSession();
    }

    /**
     * 从集合中删除 session,会返回删除的 session
     * @param session 连接对象的session
     */
    public static WebSocketSession remove(WebSocketSession session) {
        return sessionGroup.remove(session.getId()).getWebSocketSession();
    }

    /**
     * 删除并关闭 连接
     * @param key 通过session.getId()得到
     */
    public static void removeAndClose(String key) {
        WebSocketSession session = remove(key);
        if (session != null) {
            try {
                // 关闭连接
                session.close();
            } catch (IOException e) {
                logger.error("关闭出现异常处理",e);
                e.printStackTrace();
            }
        }
    }

 	/**
     * 删除并关闭 连接
     * @param session 连接对象的session
     */
    public static void removeAndClose(WebSocketSession session) {
        WebSocketSession session2 = remove(session);
        if (session2 != null) {
            try {
                // 关闭连接
                session.close();
            } catch (IOException e) {
                logger.error("关闭出现异常处理",e);
                e.printStackTrace();
            }
        }
    }

    /**
     * 从集合中获得 session
     * @param key 通过session.getId()得到
     */
    public static WebSocketSession get(String key) {
        return sessionGroup.get(key).getWebSocketSession();
    }


    /**
     * [描述] 从ws地址中获取用户id
     * 格式:ws://IP:端口/webSocketByNotice?userId=10000000
     */
    public static String getUserIdBySession(WebSocketSession session){
        String uri = Objects.requireNonNull(session.getUri()).toString();
        uri =  uri.substring(uri.indexOf("?")+1);
        uri =  uri.replace("userId=","").trim();
        return uri;
    }

}
/**
 * @author WeiDaPang
 */
@Service
public class WsService {


    /**
     * 发送消息给指定客户端
     * @param session 客户端session
     * @param text 发送消息的内容
     */
    public synchronized  void sendMsg(WebSocketSession session, String text) throws IOException {
        session.sendMessage(new TextMessage(text));
        Notice notice = new Notice();
        notice.setNoticeTitle("消息标题");
        notice.setNoticeContent(text);
        notice.setCreateTime(new Date());
        // 发送一条消息 就广播给所有人
        broadcastMsg(JSONUtil.toJsonStr(notice));
    }
    /**
     * 发送消息给指定客户端
     * @param session 客户端session
     * @param notice 通知
     */
    public synchronized  void sendMsgByNotice(WebSocketSession session, Notice notice) throws IOException {
        session.sendMessage(new TextMessage(JSONUtil.toJsonStr(notice)));
    }



    /**
     * 发送消息给所有客户端,客户端的session必须在WebSocketSessionManager的sessionGroup中
     * @param text 发送消息的内容
     */
    public synchronized void broadcastMsg(String text) throws IOException {
        for (WebSocketEntity entity: WebSocketSessionManager.sessionGroup.values()) {
            entity.getWebSocketSession().sendMessage(new TextMessage(text));
        }
    }

}
三、测试html页面代码:
<!DOCTYPE HTML>
<html lang="UTF-8">
<head>
    <title>WebSocket 测试页面</title>
</head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<body>
<input id="text" type="text" />
<button onclick="send()">发送消息</button>
<button onclick="closeWebSocket()">关闭webScoket连接</button>
<div id="message"></div>
</body>

<script type="text/javascript">
    // 连接到WebSocket的url地址。格式为  ws://ip:接口启动的端口/webSocketDemo
    // 如果 sping boot 配置文件中中配置了server.servlet.context-path ,则格式为: ws://ip:接口启动的端口/server.servlet.context-path的名称/webSocketDemo
    // 此处demo中 sping boot 配置了server.servlet.context-path 为 webSocketDemoApi
    let connectionUrl = "ws://127.0.0.1:808/webSocketByNotice?userId=10000001"
    let ws = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        ws = new WebSocket(connectionUrl);
    }else {
        alert('当前浏览器不支持 websocket')
    }

    //连接发生错误的回调方法
    ws.onerror = function () {
        setMessageInnerHTML("WebSocket连接发生错误");
    };

    //连接成功建立的回调方法
    ws.onopen = function(event) {
        console.log("ws调用连接成功回调方法")
        //ws.send("")
    }
    //接收到消息的回调方法
    ws.onmessage = function(message) {
        console.log("接收消息:" + message.data);
        if (typeof(message.data) == 'string') {
            setMessageInnerHTML(message.data);
        }
    }
    //ws连接断开的回调方法
    ws.onclose = function(e) {
        console.log("ws连接断开")
        //console.log(e)
        setMessageInnerHTML("ws close");
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        console.log(innerHTML)
        document.getElementById('message').innerHTML += '接收的消息:' + innerHTML + '<br/>';
    }

    //关闭连接
    function closeWebSocket() {
        ws.close();
    }


    //发送消息
    function send(msg) {
        if(!msg){
            msg = document.getElementById('text').value;
            console.log(msg)
            document.getElementById('message').innerHTML += "发送的消息:" + msg + '<br/>';
            ws.send(msg);
        }
    }
</script>

四、当socket和定时任务同时被引入自己的项目报错:

由于我的项目同时引入了
socket和定时任务,所以启动时候会报错,解决方式就是为socket创建一个【TaskScheduler】的bean。(第一个工具类就是解决这个问题的)

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot可以通过使用Spring框架的WebSocket模块来实现Socket通信WebSocket是一种在Web浏览器和服务器之间进行双向通信的协议,它可以实现实时通信和推送功能。 在Spring Boot中,可以通过使用@EnableWebSocket注解来启用WebSocket支持,并通过实现WebSocketHandler接口来处理WebSocket请求。具体步骤如下: 1. 添加依赖 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建WebSocket处理器 创建一个类实现WebSocketHandler接口,并实现其中的方法,例如: ``` @Component public class MyWebSocketHandler implements WebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // 连接建立后的处理 } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { // 处理收到的消息 } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { // 处理传输错误 } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { // 连接关闭后的处理 } @Override public boolean supportsPartialMessages() { return false; } } ``` 3. 配置WebSocket 在配置类中添加@EnableWebSocket注解,并实现WebSocketConfigurer接口,例如: ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Autowired private MyWebSocketHandler myWebSocketHandler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myWebSocketHandler, "/my-websocket").setAllowedOrigins("*"); } } ``` 4. 测试WebSocket 在前端页面中使用JavaScript代码连接WebSocket,并发送消息,例如: ``` var socket = new WebSocket("ws://localhost:8080/my-websocket"); socket.onopen = function() { console.log("WebSocket连接成功"); socket.send("Hello, WebSocket!"); }; socket.onmessage = function(event) { console.log("收到消息:" + event.data); }; socket.onclose = function(event) { console.log("WebSocket连接关闭"); }; ``` 以上就是使用Spring Boot实现WebSocket通信的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值