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

Springboot-接入WebSocket服務

這篇具有很好參考價值的文章主要介紹了Springboot-接入WebSocket服務。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1、依賴引入?

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

2、啟動類添加bean

public class Application {

    /**
     * 會自動注冊使用了@ServerEndpoint注解聲明的Websocket endpoint
     * 要注意,如果使用獨立的servlet容器,
     * 而不是直接使用springboot的內置容器,
     * 就不要注入ServerEndpointExporter,因為它將由容器自己提供和管理。
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}    

3、websocket服務創(chuàng)建

1、注解@ServerEndpoint("/client/websocket/{deviceId}")

2、地址參數(shù)與restful 風格一致

3、方法上通過獲取地址參數(shù) @PathParam( value = "deviceId")

4、方法getRemoteAddress() 可以獲取客戶端IP,如果是本機請求 則返回0.0.0.0.0.1

5、只能通過本地緩存對象sessionMap 存儲session信息。

6、如果需要集群、分布式,則使用Nginx 做負載均衡(IP hash)

7、如果需要bean注入其他對象,必須使用構造函數(shù)手動申明SpringUtils.getBean(RedisCache.class);


import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil; 
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 與客戶端進行socket通信服務
 * @author xuancg
 */
@ServerEndpoint("/client/websocket/{deviceId}")
@Component
@Slf4j
public class ClientSocketService {

    private RedisCache redisCache;
    private ClientProperites clientProperites; 
    /** 用于存儲當前服務器連接的socket  deviceId-session */
    private static Map<Long, Session> sessionMap = new ConcurrentHashMap<>(32);


    /**
     * 必須通過構造函數(shù)引入bean
     */
    public ClientSocketService(){
        this.redisCache = SpringUtils.getBean(RedisCache.class);
        this.clientProperites = SpringUtils.getBean(ClientProperites.class); 
        log.info("websocket準備完成");
    } 

    /**
     * 連接事件,加入注解
     * @param deviceId
     * @param session
     */
    @OnOpen
    public void onOpen(@PathParam( value = "deviceId") Long deviceId, Session session ) {
        // 設置消息體最大大小及session空閑時間
        int MAX_MESSAGE_SIZE 2 * 1024 * 1024;
        session.setMaxTextMessageBufferSize(MAX_MESSAGE_SIZE);
        session.setMaxBinaryMessageBufferSize(MAX_MESSAGE_SIZE);
        session.setMaxIdleTimeout(1 * 1000 * 60);
        log.info("客戶端發(fā)起連接deviceId={}", deviceId);
       
    }

    /**
     * 連接事件,加入注解
     * 用戶斷開鏈接
     * 此處不允許執(zhí)行刪除sessionMap操作。由于deviceId 可能是惡意構造,需要做其他參數(shù),
        或者請求token 驗證,或者通過接收消息關閉onMessage
     * @param deviceId
     * @param session
     */
    @OnClose
    public void onClose(@PathParam ( value = "deviceId") Long deviceId, Session session ) {
        log.info("客戶端關閉連接deviceId={}", deviceId);
        close(session);
    }

    /**
     * 當接收到用戶上傳的消息
     * @param deviceId
     * @param session
     */
    @OnMessage
    public void onMessage(@PathParam ( value = "deviceId") Long deviceId, Session session ,String message) {
        log.info("接收客戶端請求 deviceId=,message={}", deviceId, message);
         
    }
  


    /**
     * 給單個用戶推送消息
     * @param session
     * @param message
     */
    private void sendMessage(Session session, ClientNotifyResp message){
        if(session == null){
            return;
        }
        // 同步
        RemoteEndpoint.Async async = session.getAsyncRemote();
        async.sendText(JSONUtil.toJsonStr(message));
    }

    /**
     * 處理用戶活連接異常
     * @param session
     * @param throwable
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        throwable.printStackTrace();
    }

    private void close(Session session){
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String getRemoteAddress(Session session) {
        if (session == null) {
            return null;
        }
        RemoteEndpoint.Async async = session.getAsyncRemote();

        //在Tomcat 8.0.x版本有效
        //InetSocketAddress addr0 = (InetSocketAddress) getFieldInstance(async,"base#sos#socketWrapper#socket#sc#remoteAddress");
        //System.out.println("clientIP0" + addr0);
        //在Tomcat 8.5以上版本有效
        Object obj = getFieldInstance(async, "base#socketWrapper#socket#sc#remoteAddress");
        if(null == obj){
            return "127.0.0.1";
        }
        InetSocketAddress addr = (InetSocketAddress) obj;
        String ip = addr.toString().replace("/", "");
        int idx = ip.lastIndexOf(":");
        if(idx > 0){
            return ip.substring(0, idx);
        }
        return ip;
    }

    private static Object getFieldInstance(Object obj, String fieldPath) {
        String fields[] = fieldPath.split("#");
        for (String field : fields) {
            obj = getField(obj, obj.getClass(), field);
            if (obj == null) {
                return null;
            }
        }

        return obj;
    }

    private static Object getField(Object obj, Class<?> clazz, String fieldName) {
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                Field field;
                field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (Exception e) {
            }
        }

        return null;
    }



}

4、攔截器放行

或者添加自定義攔截器文章來源地址http://www.zghlxwxcb.cn/news/detail-830209.html

httpSecurity
// CSRF禁用,因為不使用session TODO
.csrf().disable()
// 認證失敗處理類
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 過濾請求
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/client/websocket/**").permitAll()

5、客戶端調用demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Java后端WebSocket的Tomcat實現(xiàn)</title>
</head>
<body>
Welcome<br/><input id="text" type="text"/>
<button onclick="send()">發(fā)送消息</button>
<hr/>
<button onclick="closeWebSocket()">關閉WebSocket連接</button>
<hr/>
<div id="message"></div>
</body>

<script type="text/javascript">
    var websocket = null;
    //判斷當前瀏覽器是否支持WebSocket
    if ('WebSocket' in window) {
        websocket = new WebSocket('ws://localhost:8080/mood-service/client/websocket/200013');
    }
    else {
        alert('當前瀏覽器 Not support websocket')
    }

    //連接發(fā)生錯誤的回調方法
    websocket.onerror = function () {
        setMessageInnerHTML("WebSocket連接發(fā)生錯誤");
    };

    //連接成功建立的回調方法
    websocket.onopen = function () {
        setMessageInnerHTML("WebSocket連接成功");
    }

    //接收到消息的回調方法
    websocket.onmessage = function (event) {
        setMessageInnerHTML(event.data);
    }

    //連接關閉的回調方法
    websocket.onclose = function () {
        setMessageInnerHTML("WebSocket連接關閉");
    }

    //監(jiān)聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }

    //將消息顯示在網(wǎng)頁上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //關閉WebSocket連接
    function closeWebSocket() {
        websocket.close();
    }

    //發(fā)送消息
    function send() {
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
</script>
</html>

到了這里,關于Springboot-接入WebSocket服務的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領支付寶紅包贊助服務器費用

相關文章

  • Spring Boot進階(49):SpringBoot之集成WebSocket實現(xiàn)前后端通信 | 超級詳細,建議收藏

    Spring Boot進階(49):SpringBoot之集成WebSocket實現(xiàn)前后端通信 | 超級詳細,建議收藏

    ????????在上一期,我對WebSocket進行了基礎及理論知識普及學習,WebSocket是一種基于TCP協(xié)議實現(xiàn)的全雙工通信協(xié)議,使用它可以實現(xiàn)實時通信,不必擔心HTTP協(xié)議的短連接問題。Spring Boot作為一款微服務框架,也提供了輕量級的WebSocket集成支持,本文將介紹如何在Spring Boot項

    2024年02月14日
    瀏覽(27)
  • WebSocket服務端數(shù)據(jù)推送及心跳機制(Spring Boot + VUE)

    WebSocket服務端數(shù)據(jù)推送及心跳機制(Spring Boot + VUE)

    一、WebSocket簡介 HTML5規(guī)范在傳統(tǒng)的web交互基礎上為我們帶來了眾多的新特性,隨著web技術被廣泛用于web APP的開發(fā),這些新特性得以推廣和使用,而websocket作為一種新的web通信技術具有巨大意義。WebSocket是HTML5新增的協(xié)議,它的目的是在瀏覽器和服務器之間建立一個不受限的雙

    2024年02月12日
    瀏覽(25)
  • 服務端(后端)主動通知前端的實現(xiàn):WebSocket(springboot中使用WebSocket案例)

    我們都知道 http 協(xié)議只能瀏覽器單方面向服務器發(fā)起請求獲得響應,服務器不能主動向瀏覽器推送消息。想要實現(xiàn)瀏覽器的主動推送有兩種主流實現(xiàn)方式: 輪詢:缺點很多,但是實現(xiàn)簡單 websocket:在瀏覽器和服務器之間建立 tcp 連接,實現(xiàn)全雙工通信 springboot 使用 websocket 有

    2023年04月14日
    瀏覽(36)
  • Spring Boot 集成 WebSocket 實現(xiàn)服務端推送消息到客戶端

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

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

    2024年02月16日
    瀏覽(87)
  • Spring boot3簡單實現(xiàn)websocket(攔截器,跨域,服務端發(fā)送)
  • Spring Boot進階(49):實時通信不再是夢想,SpringBoot+WebSocket助你輕松實現(xiàn)前后端即時通訊!

    Spring Boot進階(49):實時通信不再是夢想,SpringBoot+WebSocket助你輕松實現(xiàn)前后端即時通訊!

    ????????在上一期,我對WebSocket進行了基礎及理論知識普及學習,WebSocket是一種基于TCP協(xié)議實現(xiàn)的全雙工通信協(xié)議,使用它可以實現(xiàn)實時通信,不必擔心HTTP協(xié)議的短連接問題。Spring Boot作為一款微服務框架,也提供了輕量級的WebSocket集成支持,本文將介紹如何在Spring Boot項

    2024年02月11日
    瀏覽(21)
  • 【微服務】Spring Boot集成ELK實用案例

    【微服務】Spring Boot集成ELK實用案例

    推薦一款我一直在用國內很火的 AI網(wǎng)站 ,包含 GPT3.5/4.0、文心一言、通義千問、智譜AI等多個AI模型 ,支持PC、APP、VScode插件同步使用,點擊鏈接跳轉-ChatGPT4.0中文版 在現(xiàn)代軟件開發(fā)中,微服務架構已成為一種流行趨勢。隨之而來的挑戰(zhàn)之一是如何有效地管理和分析分布在各個

    2024年02月20日
    瀏覽(20)
  • 【項目實戰(zhàn)】基于netty-websocket-spring-boot-starter實現(xiàn)WebSocket服務器長鏈接處理

    【項目實戰(zhàn)】基于netty-websocket-spring-boot-starter實現(xiàn)WebSocket服務器長鏈接處理

    項目中需要建立客戶端與服務端之間的長鏈接,首先就考慮用WebSocket,再來SpringBoot原來整合WebSocket方式并不高效,因此找到了netty-websocket-spring-boot-starter 這款腳手架,它能讓我們在SpringBoot中使用Netty來開發(fā)WebSocket服務器,并像spring-websocket的注解開發(fā)一樣簡單 2.1.1 @ServerEndpo

    2024年02月12日
    瀏覽(24)
  • 【SpringBoot】Spring Boot 單體應用升級 Spring Cloud 微服務

    Spring Cloud 是在 Spring Boot 之上構建的一套微服務生態(tài)體系,包括服務發(fā)現(xiàn)、配置中心、限流降級、分布式事務、異步消息等,因此通過增加依賴、注解等簡單的四步即可完成 Spring Boot 應用到 Spring Cloud 升級。 Spring Boot 應用升級為 Spring Cloud Cloud Native 以下是應用升級 Spring Clou

    2024年02月02日
    瀏覽(17)
  • Spring/Spring boot項目接入traceId

    分布式系統(tǒng)中,由多個服務構成,每個請求路由過來后,會在多個服務中留下追蹤ID,可以基于此追蹤ID排查問題,分析請求的執(zhí)行鏈路。 業(yè)界也有比較成熟的鏈路追蹤ID方案,比如Skywalking,它基于動態(tài)字節(jié)碼技術,本身會增加系統(tǒng)的復雜性,以及它需要單獨部署服務對信息

    2024年01月24日
    瀏覽(13)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領取紅包

二維碼2

領紅包