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

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

這篇具有很好參考價(jià)值的文章主要介紹了Spring Boot 集成 WebSocket 實(shí)例 | 前端持續(xù)打印遠(yuǎn)程日志文件更新內(nèi)容(模擬 tail 命令)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

這個(gè)是我在 CSDN 的第一百篇原則博文,留念??

#1 需求說(shuō)明

先說(shuō)下項(xiàng)目結(jié)構(gòu),后端基于 Spring Boot 3,前端為 node.js 開(kāi)發(fā)的控制臺(tái)程序?,F(xiàn)在希望能夠在前端模擬 tail 命令,持續(xù)輸出后端的日志文件。

#2 技術(shù)方案

#2.1 基于輪詢(xún)(PASS)

這個(gè)方案實(shí)施較為簡(jiǎn)單,通過(guò)前端不斷(定時(shí))發(fā)起請(qǐng)求,并攜帶已讀的內(nèi)容坐標(biāo)(position),詢(xún)問(wèn)后端日志文件是否有更新,判斷依據(jù)為當(dāng)前文件大小大于 position。若有變動(dòng),則讀取更新的內(nèi)容,回顯在前端控制臺(tái)。

此方案會(huì)產(chǎn)生非常多的請(qǐng)求,如果定時(shí)間隔設(shè)置不好,會(huì)有明顯的延遲,故不采用。

#2.2 WebSocket 長(zhǎng)連接

  1. 前端開(kāi)啟一個(gè) WebSocket
  2. 后端監(jiān)聽(tīng)到長(zhǎng)連接后,啟動(dòng)文件變動(dòng)檢測(cè)線(xiàn)程
  3. 若文件發(fā)生變動(dòng),則讀取更新內(nèi)容,發(fā)送到前端

#3 實(shí)施

#3.1 后端改造

關(guān)于 Spring Boot 與 WebSocket 的集成,請(qǐng)轉(zhuǎn)到:springboot集成websocket持久連接(權(quán)限過(guò)濾+攔截)

首先,我們定義一個(gè)監(jiān)聽(tīng)文件變動(dòng)并讀取最新內(nèi)容的工具類(lèi)(借助于 common-io 包):

class FileTail(val path:Path, val handler: Consumer<String>, delay:Long=1000): FileAlterationListenerAdaptor() {
    private val watcher = FileSystems.getDefault().newWatchService()

    private val MODE = "r"
    private var reader = RandomAccessFile(path.toFile(), MODE)
    private var position= reader.length()

    // 使用 JDK 自帶的 WatchService ,發(fā)現(xiàn)不能正常讀取文件追加的內(nèi)容
    private var monitor: FileAlterationMonitor = FileAlterationMonitor(delay)

    init {
        // 初始化監(jiān)視器,只檢測(cè)同名的文件
        FileAlterationObserver(path.parent.toFile()) { f: File -> f.name == path.name }.also { observer->
            observer.addListener(this)
            monitor.addObserver(observer)

            monitor.start()
        }
    }

    override fun onFileChange(file: File) {
        reader.seek(position)

        val bytes = mutableListOf<Byte>()
        val tmp = ByteArray(1024)
        var readSize: Int

        while ((reader.read(tmp).also { readSize = it }) != -1) {
            for (i in 0..< readSize){
                bytes.add(tmp[i])
            }
        }

        position += bytes.size
        handler.accept(String(bytes.toByteArray()))
    }
    
    fun stop() {
        reader.close()
        monitor.stop()
    }
}

再定義長(zhǎng)連接的通信處理類(lèi):

@Component
class FileTailWsHandler : TextWebSocketHandler() {
    private val logger = LoggerFactory.getLogger(javaClass)

    companion object {
        val monitors = mutableMapOf<String, FileTail>()
    }

    override fun afterConnectionEstablished(session: WebSocketSession) {
        try{
             val textFile = Paths.get("logs/spring.log")

            // 加入隊(duì)列
            monitors[session.id] = FileTail(
                textFile,
                { text -> session.sendMessage(TextMessage(text)) }
            )
        }catch (e:Exception){
            logger.error("處理客戶(hù)端消息失敗", e)
            session.sendMessage(TextMessage("服務(wù)器出錯(cuò):${ExceptionUtils.getMessage(e)}"))
            session.close(CloseStatus.SERVER_ERROR)
        }
    }

    override fun afterConnectionClosed(session: WebSocketSession, status: CloseStatus) {
        logger.info("客戶(hù)端(${session.id}${session.remoteAddress} 斷開(kāi)連接...")

        monitors.remove(session.id)?.stop()
    }
}

編寫(xiě)配置類(lèi),啟用上述的組件:

@Component
class WsInterceptor : HandshakeInterceptor {
    private val logger = LoggerFactory.getLogger(javaClass)

    override fun beforeHandshake(
        request: ServerHttpRequest,
        response: ServerHttpResponse,
        wsHandler: WebSocketHandler,
        attributes: MutableMap<String, Any>
    ): Boolean {
        if(logger.isDebugEnabled){
            logger.debug("WS 握手開(kāi)始:${request.uri} 客戶(hù)端=${request.remoteAddress}")
            request.headers.forEach { name, v -> logger.debug("[HEADER] $name = $v") }
        }
		//此處可以進(jìn)行鑒權(quán)
	
		//寫(xiě)入屬性值,方便在 handler 中獲取
        attributes[F.PARAMS]    = request.headers.getFirst(F.PARAMS)?: EMPTY
        // 返回 true 才能建立連接
        return true
    }

    override fun afterHandshake(
        request: ServerHttpRequest,
        response: ServerHttpResponse,
        wsHandler: WebSocketHandler,
        exception: Exception?
    ) {
    }
}

@Configuration
@EnableWebSocket
class SocketConfig : WebSocketConfigurer {
    private val logger = LoggerFactory.getLogger(javaClass)

    @Resource
    lateinit var interceptor: WsInterceptor
    @Resource
    lateinit var fileTailHandler:FileTailWsHandler

    override fun registerWebSocketHandlers(registry: WebSocketHandlerRegistry) {
        registry.addHandler(fileTailHandler, "/ws/file-tail").addInterceptors(interceptor)
	}
}

#3.2 前端(node.js)

請(qǐng)先安裝依賴(lài):npm i -D ws

/**
 * 跟蹤遠(yuǎn)程日志文件
 * @param {*} ps
 */
const _tailRemoteFile = async ps=>{
    let url = remoteUrl("/ws/file-tail")
    let index = url.indexOf("://")

    let headers = {}
    headers.params = JSON.stringify(ps)

    const client = new WebSocket(`ws${url.substring(index)}`, { headers })
    client.on('open', ()=> console.debug(chalk.magenta(`與服務(wù)器連接成功 ??`)))
    // client.on('close',()=> console.debug(chalk.magenta(`\n與服務(wù)器連接關(guān)閉 ??`)))
    client.on('error', e=> {
        console.debug(chalk.red(e))
    })
    client.on('message', /** @param {Buffer} buf */buf=>{
        let line = buf.toString()
        if(line.endsWith("\n") || line.endsWith("\r\n"))
            line = line.substring(0, line.length-2)
        console.debug(line)
    })
}

#3.3 看看效果

Spring Boot 集成 WebSocket 實(shí)例 | 前端持續(xù)打印遠(yuǎn)程日志文件更新內(nèi)容(模擬 tail 命令),低代碼/Low-Code,JAVA,前端,spring boot,websocket,node.js文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-841116.html

到了這里,關(guān)于Spring Boot 集成 WebSocket 實(shí)例 | 前端持續(xù)打印遠(yuǎn)程日志文件更新內(nèi)容(模擬 tail 命令)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(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)文章

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

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

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

    2024年02月16日
    瀏覽(87)
  • Spring Boot進(jìn)階(48):【實(shí)戰(zhàn)教程】SpringBoot集成WebSocket輕松實(shí)現(xiàn)實(shí)時(shí)消息推送

    Spring Boot進(jìn)階(48):【實(shí)戰(zhàn)教程】SpringBoot集成WebSocket輕松實(shí)現(xiàn)實(shí)時(shí)消息推送

    ????????WebSocket是一種新型的通信協(xié)議,它可以在客戶(hù)端與服務(wù)器端之間實(shí)現(xiàn)雙向通信,具有低延遲、高效性等特點(diǎn),適用于實(shí)時(shí)通信場(chǎng)景。在SpringBoot應(yīng)用中,集成WebSocket可以方便地實(shí)現(xiàn)實(shí)時(shí)通信功能,如即時(shí)聊天、實(shí)時(shí)數(shù)據(jù)傳輸?shù)取?????????本文將介紹如何在Sprin

    2024年02月09日
    瀏覽(97)
  • Spring Boot進(jìn)階(48):SpringBoot之集成WebSocket及使用說(shuō)明 | 超級(jí)詳細(xì),建議收藏

    Spring Boot進(jìn)階(48):SpringBoot之集成WebSocket及使用說(shuō)明 | 超級(jí)詳細(xì),建議收藏

    ????????WebSocket是一種新型的通信協(xié)議,它可以在客戶(hù)端與服務(wù)器端之間實(shí)現(xiàn)雙向通信,具有低延遲、高效性等特點(diǎn),適用于實(shí)時(shí)通信場(chǎng)景。在SpringBoot應(yīng)用中,集成WebSocket可以方便地實(shí)現(xiàn)實(shí)時(shí)通信功能,如即時(shí)聊天、實(shí)時(shí)數(shù)據(jù)傳輸?shù)取?????????本文將介紹如何在Sprin

    2024年02月16日
    瀏覽(30)
  • Spring Boot進(jìn)階(49):SpringBoot之集成WebSocket實(shí)現(xiàn)前后端通信 | 超級(jí)詳細(xì),建議收藏

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

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

    2024年02月14日
    瀏覽(27)
  • Spring Boot整合WebSocket實(shí)現(xiàn)實(shí)時(shí)通信,前端實(shí)時(shí)通信,前后端實(shí)時(shí)通信

    實(shí)時(shí)通信在現(xiàn)代Web應(yīng)用中扮演著越來(lái)越重要的角色,無(wú)論是在線(xiàn)聊天、股票價(jià)格更新還是實(shí)時(shí)通知,WebSocket都是實(shí)現(xiàn)這些功能的關(guān)鍵技術(shù)之一。Spring Boot作為一個(gè)簡(jiǎn)化企業(yè)級(jí)應(yīng)用開(kāi)發(fā)的框架,其對(duì)WebSocket的支持也非常友好。本文將詳細(xì)介紹如何在Spring Boot中整合WebSocket,實(shí)現(xiàn)一

    2024年04月27日
    瀏覽(51)
  • sanic 使用websocket與前端vue通信,持續(xù)發(fā)送信息

    由于sanic使用較少,很難獲取到有效信息,而且對(duì)websocket也是挺“一竅不通”的,因此寫(xiě)一下總結(jié)。在使用過(guò)程中,對(duì)sanic注冊(cè)websocket,還是使用socketio不清。前端vue是使用io,還是WebSocket還是VueSocketIO。 API:sanic.add_websocket_route是Sanic框架自帶的一個(gè)方法,用于添加WebSocket路由

    2024年02月11日
    瀏覽(22)
  • 前端面試:【代碼質(zhì)量與工程實(shí)踐】單元測(cè)試、集成測(cè)試和持續(xù)集成

    在現(xiàn)代軟件開(kāi)發(fā)中,確保代碼質(zhì)量是至關(guān)重要的。單元測(cè)試、集成測(cè)試和持續(xù)集成是關(guān)鍵的工程實(shí)踐,用于提高代碼的可靠性和可維護(hù)性。本文將深入探討這些概念,以及它們?nèi)绾卧谲浖_(kāi)發(fā)中發(fā)揮作用。 1. 單元測(cè)試(Unit Testing): 單元測(cè)試是一種測(cè)試方法,用于驗(yàn)證代碼

    2024年02月11日
    瀏覽(33)
  • 持續(xù)集成交付CICD:Jenkins Pipeline與遠(yuǎn)程構(gòu)建觸發(fā)器

    持續(xù)集成交付CICD:Jenkins Pipeline與遠(yuǎn)程構(gòu)建觸發(fā)器

    目錄 一、實(shí)驗(yàn) 1.Jenkins Pipeline本地構(gòu)建觸發(fā)器 2.Jenkins Pipeline與遠(yuǎn)程構(gòu)建觸發(fā)器(第一種方式) 3.Jenkins Pipeline與遠(yuǎn)程構(gòu)建觸發(fā)器(第二種方式) 4.Jenkins Pipeline與遠(yuǎn)程構(gòu)建觸發(fā)器(第三種方式) 二、問(wèn)題 1.pipeline插件依賴(lài)安裝報(bào)錯(cuò) 2.控制臺(tái)輸出環(huán)境變量名沖突 3.并行構(gòu)建job存在

    2024年02月03日
    瀏覽(28)
  • Spring Boot整合WebSocket

    Spring Boot整合WebSocket

    在HTTP協(xié)議中,所有的請(qǐng)求都是由客戶(hù)端發(fā)起的,由服務(wù)端進(jìn)行響應(yīng),服務(wù)端無(wú)法向客戶(hù)端推送消息,但是在一些需要即時(shí)通信的應(yīng)用中,又不可避免地需要服務(wù)端向客戶(hù)端推送消息,傳統(tǒng)的解決方案主要有如下幾種。 輪詢(xún) 輪詢(xún)是最簡(jiǎn)單的一種解決方案,所謂輪詢(xún),就是客戶(hù)

    2024年02月05日
    瀏覽(23)
  • 在Spring Boot中打印SQL語(yǔ)句的方法

    在Spring Boot項(xiàng)目中,調(diào)試和優(yōu)化數(shù)據(jù)庫(kù)操作是很常見(jiàn)的需求。通過(guò)打印SQL語(yǔ)句可以幫助開(kāi)發(fā)人員快速了解數(shù)據(jù)庫(kù)的操作情況,進(jìn)而進(jìn)行性能分析和調(diào)試。本文將介紹在Spring Boot中打印SQL語(yǔ)句的幾種方法,幫助你更好地理解和優(yōu)化數(shù)據(jù)庫(kù)操作。 Spring Boot提供了一個(gè)配置選項(xiàng),可以

    2024年02月06日
    瀏覽(13)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包