[后端] webSocket demo跑通
This commit is contained in:
		@@ -103,6 +103,12 @@
 | 
			
		||||
            <groupId>com.squareup.okhttp3</groupId>
 | 
			
		||||
            <artifactId>okhttp</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- WebSocket -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-websocket</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
    </dependencies>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
package com.cxyxiaomo.epp.access.config;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.ServletContext;
 | 
			
		||||
import javax.servlet.ServletException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 开启WebSocket支持
 | 
			
		||||
 */
 | 
			
		||||
@Configuration
 | 
			
		||||
public class WebSocketConfig implements ServletContextInitializer {
 | 
			
		||||
    /**
 | 
			
		||||
     * 这个bean的注册,用于扫描带有@ServerEndpoint的注解成为websocket,如果你使用外置的tomcat就不需要该配置文件
 | 
			
		||||
     */
 | 
			
		||||
    @Bean
 | 
			
		||||
    public ServerEndpointExporter serverEndpointExporter() {
 | 
			
		||||
        return new ServerEndpointExporter();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onStartup(ServletContext servletContext) throws ServletException {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,112 @@
 | 
			
		||||
package com.cxyxiaomo.epp.access.controller;
 | 
			
		||||
 | 
			
		||||
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("/websocket/{userId}")
 | 
			
		||||
@Component
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class WebSocketServer {
 | 
			
		||||
    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
 | 
			
		||||
    private Session session;
 | 
			
		||||
 | 
			
		||||
    // session集合,存放对应的session
 | 
			
		||||
    private static ConcurrentHashMap<Integer, Session> sessionPool = new ConcurrentHashMap<>();
 | 
			
		||||
 | 
			
		||||
    // concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。
 | 
			
		||||
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 建立WebSocket连接
 | 
			
		||||
     *
 | 
			
		||||
     * @param session
 | 
			
		||||
     * @param userId  用户ID
 | 
			
		||||
     */
 | 
			
		||||
    @OnOpen
 | 
			
		||||
    public void onOpen(Session session, @PathParam(value = "userId") Integer userId) {
 | 
			
		||||
        log.info("WebSocket建立连接中,连接用户ID:{}", userId);
 | 
			
		||||
        try {
 | 
			
		||||
            Session historySession = sessionPool.get(userId);
 | 
			
		||||
            // historySession不为空,说明已经有人登陆账号,应该删除登陆的WebSocket对象
 | 
			
		||||
            if (historySession != null) {
 | 
			
		||||
                webSocketSet.remove(historySession);
 | 
			
		||||
                historySession.close();
 | 
			
		||||
            }
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            log.error("重复登录异常,错误信息:" + e.getMessage(), e);
 | 
			
		||||
        }
 | 
			
		||||
        // 建立连接
 | 
			
		||||
        this.session = session;
 | 
			
		||||
        webSocketSet.add(this);
 | 
			
		||||
        sessionPool.put(userId, session);
 | 
			
		||||
        log.info("建立连接完成,当前在线人数为:{}", webSocketSet.size());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 发生错误
 | 
			
		||||
     *
 | 
			
		||||
     * @param throwable e
 | 
			
		||||
     */
 | 
			
		||||
    @OnError
 | 
			
		||||
    public void onError(Throwable throwable) {
 | 
			
		||||
        throwable.printStackTrace();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 连接关闭
 | 
			
		||||
     */
 | 
			
		||||
    @OnClose
 | 
			
		||||
    public void onClose() {
 | 
			
		||||
        webSocketSet.remove(this);
 | 
			
		||||
        log.info("连接断开,当前在线人数为:{}", webSocketSet.size());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 接收客户端消息
 | 
			
		||||
     *
 | 
			
		||||
     * @param message 接收的消息
 | 
			
		||||
     */
 | 
			
		||||
    @OnMessage
 | 
			
		||||
    public void onMessage(String message) {
 | 
			
		||||
        log.info("收到客户端发来的消息:{}", message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 推送消息到指定用户
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId  用户ID
 | 
			
		||||
     * @param message 发送的消息
 | 
			
		||||
     */
 | 
			
		||||
    public static void sendMessageByUser(Integer userId, String message) {
 | 
			
		||||
        log.info("用户ID:" + userId + ",推送内容:" + message);
 | 
			
		||||
        Session session = sessionPool.get(userId);
 | 
			
		||||
        try {
 | 
			
		||||
            session.getBasicRemote().sendText(message);
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            log.error("推送消息到指定用户发生错误:" + e.getMessage(), e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 群发消息
 | 
			
		||||
     *
 | 
			
		||||
     * @param message 发送的消息
 | 
			
		||||
     */
 | 
			
		||||
    public static void sendAllMessage(String message) {
 | 
			
		||||
        log.info("发送消息:{}", message);
 | 
			
		||||
        for (WebSocketServer webSocket : webSocketSet) {
 | 
			
		||||
            try {
 | 
			
		||||
                webSocket.session.getBasicRemote().sendText(message);
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                log.error("群发消息发生错误:" + e.getMessage(), e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
package com.cxyxiaomo.epp.access.pojo;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@Accessors(chain = true) // 链式写法
 | 
			
		||||
public class WebSocketData {
 | 
			
		||||
    // 小程序: "miniprogram"  门禁: "guard"
 | 
			
		||||
    private String type;
 | 
			
		||||
 | 
			
		||||
    // 需要执行的动作
 | 
			
		||||
    private String action;
 | 
			
		||||
 | 
			
		||||
    // 传输的数据(JSON字符串)
 | 
			
		||||
    private String json;
 | 
			
		||||
}
 | 
			
		||||
@@ -127,6 +127,13 @@
 | 
			
		||||
                <version>4.10.0</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- WebSocket -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.springframework.boot</groupId>
 | 
			
		||||
                <artifactId>spring-boot-starter-websocket</artifactId>
 | 
			
		||||
                <version>2.7.6</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- Fastjson -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.alibaba.fastjson2</groupId>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user