java websocket详细

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

一:先导入上面的jar

二:放入websocket 相关配置代码

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller
 * 直接@ServerEndpoint("/websocket")@Component启用即可,然后在里面实现@OnOpen,@onClose,@onMessage等方法
 *
 * @author Admin
 */
@ServerEndpoint("/shdxmh/websocket/{deptId}")
@Component
@RestController
public class WebSocketAction {

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

    /**
     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;

    /**
     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     */
    private static CopyOnWriteArraySet<WebSocketAction> webSocketSet = new CopyOnWriteArraySet<WebSocketAction>();

    /**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 接收sid
     */
    private String deptId = "";

    private static ExecutorService executorService = Executors.newFixedThreadPool(10);

    /**
     * 连接建立成功调用的方法
     *
     * @param deptId  唯一性ID
     * @param session socket session
     * @return void
     */
    @OnOpen
    public void onOpen(@PathParam("deptId") String deptId, Session session) {
        this.session = session;
        //加入set中
        webSocketSet.add(this);

        //添加在线人数
        addOnlineCount();
        this.deptId = deptId;
        // logger.info("新连接接入,deptId={}, sessionId={}, 当前在线人数为:{}", this.deptId, session.getId(), getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        //从set中删除
        webSocketSet.remove(this);
        //在线数减1
        subOnlineCount();
        // logger.info("有连接关闭, sessionId={}。当前在线人数为:{}", session.getId(), getOnlineCount());
    }


    /**
     * 暴露给外部的群发
     *
     * @param message
     * @throws IOException
     */
    @RequestMapping("/websocket-send")
    public static void sendInfo(String message, @PathParam("deptId") String deptId) {
        executorService.execute(() -> {
            logger.info("推送消息到窗口" + deptId + ",推送内容:" + message);
            for (WebSocketAction item : webSocketSet) {
                try {
                    //这里可以设定只推送给这个sid的,为null则全部推送
                    if (deptId == null) {
                        item.sendMessage(message);
                    }
                    //点对点推送
                    else if (item.deptId.equals(deptId)) {
                        item.sendMessage(message);
                    }
                } catch (IOException e) {
                    logger.error("推送异常", e);
                }
            }
        });
    }

    /**
     * 群发
     *
     * @param message
     */
    private static void sendAll(String message) {

        for (WebSocketAction webSocketAction : webSocketSet) {
            try {
                webSocketAction.sendMessage(message);
            } catch (IOException e) {
                logger.error("群发异常", e);
            }
        }
    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("websocket异常, sessionId={}",session.getId(), error);
    }

    /**
     * 减少在线人数
     */
    private synchronized static void subOnlineCount() {
        WebSocketAction.onlineCount--;
    }

    /**
     * 添加在线人数
     */
    private synchronized static void addOnlineCount() {
        WebSocketAction.onlineCount++;
    }

    /**
     * 当前在线人数
     *
     * @return 在线人数
     */
    public int getOnlineCount() {
        return onlineCount;
    }

    /**
     * 发送信息实现服务器主动推送信息
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
//        logger.info("发送消息, message={}", message);
        //获取session远程基本连接发送文本消息
        // tomcat有bug, 多个线程向一个socket写数据会冲突 报IllegalStateException...[TEXT_FULL_WRITING], 故此处加锁和使用getBasicRemote
        synchronized (this.session) {
            this.session.getBasicRemote().sendText(message);
        }
//            session.getAsyncRemote().sendText(message);

    }

    /**
     * 群发
     *南桥引入
     * @param message
     */
    public static void sendAllMsg(String message) {

        for (WebSocketAction webSocketAction : webSocketSet) {
            try {
                webSocketAction.sendMessage(message);
            } catch (IOException e) {
                logger.error("群发异常", e);
            }
        }
    }

}

三:浏览器连上websocket 充当客户端

 

四:postman 调用后台接口发送信息

 

 完活!其他方法自己看。

 

posted @ 2022-05-30 11:53  90的生力军  阅读(938)  评论(0编辑  收藏  举报