国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring Boot 集成 WebSocket(原生注解與Spring封裝)

這篇具有很好參考價(jià)值的文章主要介紹了Spring Boot 集成 WebSocket(原生注解與Spring封裝)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

Spring Boot 集成 WebSocket

本章節(jié)將介紹 Spring Boot 集成 WebSocket 的兩種主要方式:原生注解與Spring封裝。

在線WebSocket測(cè)試工具

?? Spring Boot 2.x 實(shí)踐案例(代碼倉(cāng)庫(kù))

原生注解

引入依賴

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

配置文件

@Configuration
public class WebSocketConfiguration {
    /**
     * 	注入ServerEndpointExporter,
     * 	這個(gè)bean會(huì)自動(dòng)注冊(cè)使用了@ServerEndpoint注解聲明的Websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

處理消息

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {

    /**
     * 線程安全的無(wú)序的集合
     */
    private static final CopyOnWriteArraySet<Session> SESSIONS = new CopyOnWriteArraySet<>();

    /**
     * 存儲(chǔ)在線連接數(shù)
     */
    private static final Map<String, Session> SESSION_POOL = new HashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        try {
            SESSIONS.add(session);
            SESSION_POOL.put(userId, session);
            log.info("【W(wǎng)ebSocket消息】有新的連接,總數(shù)為:" + SESSIONS.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClose
    public void onClose(Session session) {
        try {
            SESSIONS.remove(session);
            log.info("【W(wǎng)ebSocket消息】連接斷開(kāi),總數(shù)為:" + SESSIONS.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnMessage
    public void onMessage(String message) {
        log.info("【W(wǎng)ebSocket消息】收到客戶端消息:" + message);
    }

    /**
     * 此為廣播消息
     *
     * @param message 消息
     */
    public void sendAllMessage(String message) {
        log.info("【W(wǎng)ebSocket消息】廣播消息:" + message);
        for (Session session : SESSIONS) {
            try {
                if (session.isOpen()) {
                    session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 此為單點(diǎn)消息
     *
     * @param userId  用戶編號(hào)
     * @param message 消息
     */
    public void sendOneMessage(String userId, String message) {
        Session session = SESSION_POOL.get(userId);
        if (session != null && session.isOpen()) {
            try {
                synchronized (session) {
                    log.info("【W(wǎng)ebSocket消息】單點(diǎn)消息:" + message);
                    session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 此為單點(diǎn)消息(多人)
     *
     * @param userIds 用戶編號(hào)列表
     * @param message 消息
     */
    public void sendMoreMessage(String[] userIds, String message) {
        for (String userId : userIds) {
            Session session = SESSION_POOL.get(userId);
            if (session != null && session.isOpen()) {
                try {
                    log.info("【W(wǎng)ebSocket消息】單點(diǎn)消息:" + message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • @ServerEndpoint:將目前的類定義成一個(gè)websocket服務(wù)器端,注解的值將被用于監(jiān)聽(tīng)用戶連接的終端訪問(wèn)URL地址,客戶端可以通過(guò)這個(gè)URL來(lái)連接到WebSocket服務(wù)器端
  • @OnOpen:當(dāng)WebSocket建立連接成功后會(huì)觸發(fā)這個(gè)注解修飾的方法。
  • @OnClose:當(dāng)WebSocket建立的連接斷開(kāi)后會(huì)觸發(fā)這個(gè)注解修飾的方法。
  • @OnMessage:當(dāng)客戶端發(fā)送消息到服務(wù)端時(shí),會(huì)觸發(fā)這個(gè)注解修改的方法。
  • @OnError:當(dāng)WebSocket建立連接時(shí)出現(xiàn)異常會(huì)觸發(fā)這個(gè)注解修飾的方法。

Spring封裝

引入依賴

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

自定義處理器

處理器作用類似于@RequestMapping注解,用于處理某一個(gè)路徑的WebSocket連接,自定義處理器需要實(shí)現(xiàn)WebSocketHandler接口。

WebSocket操作類
public interface WebSocket {
    /**
     * 會(huì)話開(kāi)始回調(diào)
     *
     * @param session 會(huì)話
     */
    void handleOpen(WebSocketSession session);

    /**
     * 會(huì)話結(jié)束回調(diào)
     *
     * @param session 會(huì)話
     */
    void handleClose(WebSocketSession session);

    /**
     * 處理消息
     *
     * @param session 會(huì)話
     * @param message 接收的消息
     */
    void handleMessage(WebSocketSession session, String message);

    /**
     * 發(fā)送消息
     *
     * @param session 當(dāng)前會(huì)話
     * @param message 要發(fā)送的消息
     * @throws IOException 發(fā)送io異常
     */
    void sendMessage(WebSocketSession session, String message) throws IOException;

    /**
     * 發(fā)送消息
     *
     * @param userId  用戶id
     * @param message 要發(fā)送的消息
     * @throws IOException 發(fā)送io異常
     */
    void sendMessage(String userId, TextMessage message) throws IOException;

    /**
     * 發(fā)送消息
     *
     * @param userId  用戶id
     * @param message 要發(fā)送的消息
     * @throws IOException 發(fā)送io異常
     */
    void sendMessage(String userId, String message) throws IOException;

    /**
     * 發(fā)送消息
     *
     * @param session 當(dāng)前會(huì)話
     * @param message 要發(fā)送的消息
     * @throws IOException 發(fā)送io異常
     */
    void sendMessage(WebSocketSession session, TextMessage message) throws IOException;

    /**
     * 廣播
     *
     * @param message 字符串消息
     * @throws IOException 異常
     */
    void broadCast(String message) throws IOException;

    /**
     * 廣播
     *
     * @param message 文本消息
     * @throws IOException 異常
     */
    void broadCast(TextMessage message) throws IOException;

    /**
     * 處理會(huì)話異常
     *
     * @param session 會(huì)話
     * @param error   異常
     */
    void handleError(WebSocketSession session, Throwable error);

    /**
     * 獲得所有的 websocket 會(huì)話
     *
     * @return 所有 websocket 會(huì)話
     */
    Set<WebSocketSession> getSessions();

    /**
     * 得到當(dāng)前連接數(shù)
     *
     * @return 連接數(shù)
     */
    int getConnectionCount();
}
WebSocket操作實(shí)現(xiàn)類
@Slf4j
public class WebSocketImpl implements WebSocket {
    /**
     * 在線連接數(shù)(線程安全)
     */
    private final AtomicInteger connectionCount = new AtomicInteger(0);

    /**
     * 線程安全的無(wú)序集合(存儲(chǔ)會(huì)話)
     */
    private final CopyOnWriteArraySet<WebSocketSession> sessions = new CopyOnWriteArraySet<>();

    @Override
    public void handleOpen(WebSocketSession session) {
        sessions.add(session);
        int count = connectionCount.incrementAndGet();
        log.info("a new connection opened,current online count:{}", count);
    }

    @Override
    public void handleClose(WebSocketSession session) {
        sessions.remove(session);
        int count = connectionCount.decrementAndGet();
        log.info("a new connection closed,current online count:{}", count);
    }

    @Override
    public void handleMessage(WebSocketSession session, String message) {
        // 只處理前端傳來(lái)的文本消息,并且直接丟棄了客戶端傳來(lái)的消息
        log.info("received a message:{}", message);
    }

    @Override
    public void sendMessage(WebSocketSession session, String message) throws IOException {
        this.sendMessage(session, new TextMessage(message));
    }

    @Override
    public void sendMessage(String userId, TextMessage message) throws IOException {
        Optional<WebSocketSession> userSession = sessions.stream().filter(session -> {
            if (!session.isOpen()) {
                return false;
            }
            Map<String, Object> attributes = session.getAttributes();
            if (!attributes.containsKey("uid") {
                return false;
            }
            String uid = (String) attributes.get("uid");
            return uid.equals(userId);
        }).findFirst();
        if (userSession.isPresent()) {
            userSession.get().sendMessage(message);
        }
    }

    @Override
    public void sendMessage(String userId, String message) throws IOException {
        this.sendMessage(userId, new TextMessage(message));
    }

    @Override
    public void sendMessage(WebSocketSession session, TextMessage message) throws IOException {
        session.sendMessage(message);
    }

    @Override
    public void broadCast(String message) throws IOException {
        for (WebSocketSession session : sessions) {
            if (!session.isOpen()) {
                continue;
            }
            this.sendMessage(session, message);
        }
    }

    @Override
    public void broadCast(TextMessage message) throws IOException {
        for (WebSocketSession session : sessions) {
            if (!session.isOpen()) {
                continue;
            }
            session.sendMessage(message);
        }
    }

    @Override
    public void handleError(WebSocketSession session, Throwable error) {
        log.error("websocket error:{},session id:{}", error.getMessage(), session.getId());
        log.error("", error);
    }

    @Override
    public Set<WebSocketSession> getSessions() {
        return sessions;
    }

    @Override
    public int getConnectionCount() {
        return connectionCount.get();
    }
}
自定義WebSocket處理器
public class DefaultWebSocketHandler implements WebSocketHandler {

    @Autowired
    private WebSocket webSocket;

    /**
     * 建立連接
     *
     * @param session Session
     */
    @Override
    public void afterConnectionEstablished(@NonNull WebSocketSession session) {
        webSocket.handleOpen(session);
    }

    /**
     * 接收消息
     *
     * @param session Session
     * @param message 消息
     */
    @Override
    public void handleMessage(@NonNull WebSocketSession session, @NonNull WebSocketMessage<?> message) {
        if (message instanceof TextMessage) {
            TextMessage textMessage = (TextMessage) message;
            webSocket.handleMessage(session, textMessage.getPayload());
        }
    }

    /**
     * 發(fā)生錯(cuò)誤
     *
     * @param session   Session
     * @param exception 異常
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        webSocket.handleError(session, exception);
    }

    /**
     * 關(guān)閉連接
     *
     * @param session     Session
     * @param closeStatus 關(guān)閉狀態(tài)
     */
    @Override
    public void afterConnectionClosed(@NonNull WebSocketSession session, @NonNull CloseStatus closeStatus) {
        webSocket.handleClose(session);
    }

    /**
     * 是否支持發(fā)送部分消息
     *
     * @return false
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}
自定義攔截器

自定義處理器需要實(shí)現(xiàn)HandshakeInterceptor接口

public class WebSocketInterceptor implements HandshakeInterceptor {

    @Override
    public boolean beforeHandshake(@NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response, @NonNull WebSocketHandler wsHandler, @NonNull Map<String, Object> attributes) throws Exception {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) request;
            // 模擬用戶(通常利用JWT令牌解析用戶信息)
            String userId = servletServerHttpRequest.getServletRequest().getParameter("uid");
            // TODO 判斷用戶是否存在
            attributes.put("uid", userId);
            return true;
        }
        return false;
    }

    @Override
    public void afterHandshake(@NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response, @NonNull WebSocketHandler wsHandler, Exception exception) {

    }
}

WebSocket 無(wú)法使用 header 傳遞參數(shù),因此這里使用 url params 攜帶參數(shù)。

WebSocket配置項(xiàng)

將自定義處理器、攔截器以及WebSocket操作類依次注入到IOC容器中。

@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {

    @Bean
    public DefaultWebSocketHandler defaultWebSocketHandler() {
        return new DefaultWebSocketHandler();
    }

    @Bean
    public WebSocket webSocket() {
        return new WebSocketImpl();
    }

    @Bean
    public WebSocketInterceptor webSocketInterceptor() {
        return new WebSocketInterceptor();
    }

    @Override
    public void registerWebSocketHandlers(@NonNull WebSocketHandlerRegistry registry) {
        registry.addHandler(defaultWebSocketHandler(), "ws/message")
                    .addInterceptors(webSocketInterceptor())
                    .setAllowedOrigins("*");
    }
}
  • @EnableWebSocket:開(kāi)啟WebSocket功能
  • addHandler:添加處理器
  • addInterceptors:添加攔截器
  • setAllowedOrigins:設(shè)置允許跨域(允許所有請(qǐng)求來(lái)源)

WebSocket測(cè)試

原生注解

springboot集成websocket,后端筆記,websocket,spring,spring boot
springboot集成websocket,后端筆記,websocket,spring,spring boot

Spring封裝

springboot集成websocket,后端筆記,websocket,spring,spring boot
springboot集成websocket,后端筆記,websocket,spring,spring boot文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-781073.html

到了這里,關(guān)于Spring Boot 集成 WebSocket(原生注解與Spring封裝)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【SpringBoot筆記37】SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket

    這篇文章,主要介紹SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket。 目錄 一、基于注解集成WebSocket 1.1、WebSocket常見(jiàn)注解 1.2、創(chuàng)建WebSocket服務(wù)端

    2024年02月14日
    瀏覽(23)
  • Spring Boot集成WebSocket實(shí)現(xiàn)消息推送

    Spring Boot集成WebSocket實(shí)現(xiàn)消息推送

    項(xiàng)目中經(jīng)常會(huì)用到消息推送功能,關(guān)于推送技術(shù)的實(shí)現(xiàn),我們通常會(huì)聯(lián)想到輪詢、comet長(zhǎng)連接技術(shù),雖然這些技術(shù)能夠?qū)崿F(xiàn),但是需要反復(fù)連接,對(duì)于服務(wù)資源消耗過(guò)大,隨著技術(shù)的發(fā)展,HtML5定義了WebSocket協(xié)議,能更好的節(jié)省服務(wù)器資源和帶寬,并且能夠更實(shí)時(shí)地進(jìn)行通訊。

    2023年04月08日
    瀏覽(21)
  • Spring Boot 集成 Redisson分布式鎖(注解版)

    Spring Boot 集成 Redisson分布式鎖(注解版)

    ????????Redisson 是一種基于 Redis 的 Java 駐留集群的分布式對(duì)象和服務(wù)庫(kù),可以為我們提供豐富的分布式鎖和線程安全集合的實(shí)現(xiàn)。在 Spring Boot 應(yīng)用程序中使用 Redisson 可以方便地實(shí)現(xiàn)分布式應(yīng)用程序的某些方面,例如分布式鎖、分布式集合、分布式事件發(fā)布和訂閱等。本篇

    2024年02月09日
    瀏覽(25)
  • Spring Boot集成WebSocket Demo,簡(jiǎn)單明了

    Spring Boot集成WebSocket Demo,簡(jiǎn)單明了

    如果是初次搭建Spring Boot+WebSocket項(xiàng)目,不需要太復(fù)雜,只需要快速上手,那么你搜到的大部分文章可能都不適合你,我的這篇文章以最精簡(jiǎn)的方式搭建一個(gè)可以運(yùn)行并通信的Spring Boot+WebSocket的Demo項(xiàng)目,有了根基之后再進(jìn)行復(fù)雜化就不是難事了。 搭建Spring Boot項(xiàng)目都會(huì)吧,下面

    2024年02月09日
    瀏覽(15)
  • Spring Boot 集成 WebSocket 實(shí)現(xiàn)服務(wù)端推送消息到客戶端

    Spring Boot 集成 WebSocket 實(shí)現(xiàn)服務(wù)端推送消息到客戶端

    ? ? ? 假設(shè)有這樣一個(gè)場(chǎng)景:服務(wù)端的資源經(jīng)常在更新,客戶端需要盡量及時(shí)地了解到這些更新發(fā)生后展示給用戶,如果是 HTTP 1.1,通常會(huì)開(kāi)啟 ajax 請(qǐng)求詢問(wèn)服務(wù)端是否有更新,通過(guò)定時(shí)器反復(fù)輪詢服務(wù)端響應(yīng)的資源是否有更新。 ? ? ? ? ? ? ? ?? ? ? ? ?在長(zhǎng)時(shí)間不更新

    2024年02月16日
    瀏覽(87)
  • 實(shí)現(xiàn)實(shí)時(shí)互動(dòng):用Spring Boot原生WebSocket打造你的專屬聊天室

    實(shí)現(xiàn)實(shí)時(shí)互動(dòng):用Spring Boot原生WebSocket打造你的專屬聊天室

    ?? @ 作者: 一恍過(guò)去 ?? @ 主頁(yè): https://blog.csdn.net/zhuocailing3390 ?? @ 社區(qū): Java技術(shù)棧交流 ?? @ 主題: 實(shí)現(xiàn)實(shí)時(shí)互動(dòng):用Spring Boot原生WebSocket打造你的專屬聊天室 ?? @ 創(chuàng)作時(shí)間: 2023年08月04日 WebSocket 實(shí)現(xiàn)聊天室的原理包括建立 WebSocket 連接的握手過(guò)程、保持連接狀態(tài)以

    2024年02月10日
    瀏覽(25)
  • 【SpringBoot】| Spring Boot 常見(jiàn)的底層注解剖析

    【SpringBoot】| Spring Boot 常見(jiàn)的底層注解剖析

    目錄 一:Spring Boot 常見(jiàn)的底層注解 1.?容器功能 1.1?組件添加 方法一:使用@Configuration注解+@Bean注解 方法二:使用@Configuration注解+@Import注解? 方法三:使用@Configuration注解+@Conditional注解? 1.2?原生xml配置文件引入 @ImportResource注解 1.3?配置綁定 方法一:@Component注解 + @Configu

    2024年02月17日
    瀏覽(28)
  • Spring Boot學(xué)習(xí)隨筆- 集成JSP模板(配置視圖解析器)、整合Mybatis(@MapperScan注解的使用)

    Spring Boot學(xué)習(xí)隨筆- 集成JSP模板(配置視圖解析器)、整合Mybatis(@MapperScan注解的使用)

    學(xué)習(xí)視頻:【編程不良人】2021年SpringBoot最新最全教程 在main創(chuàng)建webapp,然后創(chuàng)建index.jsp進(jìn)行測(cè)試,在訪問(wèn)之前需要進(jìn)行一個(gè)設(shè)置,否則springboot是找不到j(luò)sp頁(yè)面的 修改jsp無(wú)需重啟應(yīng)用 數(shù)據(jù)庫(kù)訪問(wèn)框架:hibernate、jpa、mybatis【主流】 SpringBoot(微框架) = Spring(工廠) + SpringMV

    2024年02月05日
    瀏覽(58)
  • Spring Boot 集成 WebSocket 實(shí)例 | 前端持續(xù)打印遠(yuǎn)程日志文件更新內(nèi)容(模擬 tail 命令)

    Spring Boot 集成 WebSocket 實(shí)例 | 前端持續(xù)打印遠(yuǎn)程日志文件更新內(nèi)容(模擬 tail 命令)

    這個(gè)是我在 CSDN 的第一百篇原則博文,留念?? 先說(shuō)下項(xiàng)目結(jié)構(gòu),后端基于 Spring Boot 3,前端為 node.js 開(kāi)發(fā)的控制臺(tái)程序。現(xiàn)在希望能夠在前端模擬 tail 命令,持續(xù)輸出后端的日志文件。 這個(gè)方案實(shí)施較為簡(jiǎn)單,通過(guò)前端不斷(定時(shí))發(fā)起請(qǐng)求,并攜帶已讀的內(nèi)容坐標(biāo)(posi

    2024年03月18日
    瀏覽(30)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包