日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 推送数据给js,Node.js实现数据推送

發(fā)布時(shí)間:2023/12/4 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 推送数据给js,Node.js实现数据推送 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

場景:后端更新數(shù)據(jù)推送到客戶端(Java部分使用Tomcat服務(wù)器)。

后端推送數(shù)據(jù)的解決方案有很多,比如輪詢、Comet、WebSocket。

1. 輪詢對于后端來說開發(fā)成本最低,就是按照傳統(tǒng)的方式處理Ajax請求并返回?cái)?shù)據(jù),在學(xué)校的時(shí)候?qū)嶒?yàn)室的項(xiàng)目一直都采用輪詢,因?yàn)樗畋kU(xiǎn)也最容易實(shí)現(xiàn)。但輪詢帶來的通信資源的浪費(fèi)是無法忽視的,無論數(shù)據(jù)是否改變,都照常發(fā)送請求并響應(yīng),而且每次HTTP請求都帶有很長的頭部信息。

2. Comet的概念是長連接,客戶端發(fā)送請求后,后端將連接保持下來,直到連接超時(shí)或后端返回?cái)?shù)據(jù)時(shí)再重新建立連接,有效的將通信資源轉(zhuǎn)移到了服務(wù)器上,實(shí)際消耗的是服務(wù)器資源。

3. WebSocket是HTML5提供的一種全雙工通信技術(shù),通過“握手”實(shí)現(xiàn)客戶端與服務(wù)器之間的通信,實(shí)時(shí)性好,攜帶的頭部也較小,目前支持的瀏覽器如下:

理想的情況是采取WebSocket與Comet結(jié)合的方式,對IE8等瀏覽器采取Comet方式,做降級處理。但是這樣一來,后端需要實(shí)現(xiàn)兩種處理請求的邏輯,即WebSocket與Comet。所以,本文加入Node.js,之所以這樣做,是將處理WebSocket(或Comet)的邏輯轉(zhuǎn)移到Node.js部分,不給后端“添麻煩”,因?yàn)樵趯?shí)際情況下,前端開發(fā)人員推動后端開發(fā)人員并不容易。Node.js作為瀏覽器與Java業(yè)務(wù)邏輯層通信的中間層,連接客戶端與Tomcat,通過Socket與Tomcat進(jìn)行通信(是Socket,不是WebSocket,后端需要實(shí)現(xiàn)Socket接口。

在客戶端,WebSocket與Comet通過Socket.io實(shí)現(xiàn),Socket.io會針對不同的瀏覽器版本或者不同客戶端選擇合適的實(shí)現(xiàn)方式(WebSocket, long pull..),Socket.io的引入讓處理WebSocket(或長連接)變的很容易。Socket.io

客戶端引入socket.io:

客戶端JavaScript代碼:

var socket = io.connect('127.0.0.1:8181');

// 發(fā)送數(shù)據(jù)至服務(wù)器

socket.emit('fromWebClient', jsonData);

// 從服務(wù)器接收數(shù)據(jù)

socket.on('pushToWebClient', function (data) {

// do sth.

});

Node.js服務(wù)器代碼:

var http = require('http'),

app = http.createServer().listen('8181'),

io = require('socket.io').listen(app);

io.sockets.on('connection', function (socketIO) {

// 從客戶端接收數(shù)據(jù)

socketIO.on('fromWebClient', function (webClientData) {

// do sth.

});

// 客戶端斷開連接

socketIO.on('disconnect', function () {

console.log('DISCONNECTED FROM CLIENT');

});

// 向客戶端發(fā)送數(shù)據(jù)

socketIO.emit('pushToWebClient', jsonData);

});

建立好客戶端同Node.js服務(wù)器的連接只是第一步,下面還需要建立Node.js服務(wù)器與Java業(yè)務(wù)邏輯層的聯(lián)系。這時(shí),Node.js服務(wù)器則作為客戶端,向Tomcat發(fā)送TCP連接請求。連接成功后,Node.js服務(wù)器和Tomcat建立了一條全雙工的通道,而且是唯一的一條,不論有多少個(gè)客戶端請求,都從Node.js服務(wù)器轉(zhuǎn)發(fā)至Tomcat;同樣,Tomcat推送過來的數(shù)據(jù),也經(jīng)由Node.js服務(wù)器分發(fā)至各個(gè)客戶端。

這里存在一個(gè)問題,就是在WebSocket連接與Socket連接都建立好之后,兩次連接彼此之間是屏蔽的。Tomcat不知道是哪次WebSocket連接發(fā)送過來的數(shù)據(jù),也不知道是哪個(gè)客戶端發(fā)來的數(shù)據(jù)。當(dāng)然,Node.js可以利用session id發(fā)送至Tomcat來標(biāo)識是哪一個(gè)客戶端,但本文采用的是另外一種辦法。

客戶端同Node.js建立WebSocket連接時(shí),每個(gè)連接都會包含一個(gè)實(shí)例,這里稱它為socketIO。每個(gè)socketIO都有一個(gè)id屬性用來唯一標(biāo)識這個(gè)連接,這里稱它為socket_id。利用socket_id,在Node.js服務(wù)器建立一個(gè)映射表,存儲每一個(gè)socketIO與socket_id的映射關(guān)系。Node.js服務(wù)器發(fā)送數(shù)據(jù)給Tomcat時(shí)帶上這個(gè)socket_id,再由Java部分進(jìn)行一系列處理以后封裝好每個(gè)客戶端需要的不同數(shù)據(jù)一并返回,返回的數(shù)據(jù)里要有與socket_id的對應(yīng)關(guān)系。這樣,Node.js服務(wù)器收到Tomcat發(fā)來的數(shù)據(jù)時(shí),通過前面提到的映射表由不同的socketIO分發(fā)至不同的客戶端。

Node.js服務(wù)器代碼:

var http = require('http'),

net = require('net'),

app = http.createServer().listen('8181'),

io = require('socket.io').listen(app),

nodeServer = new net.Socket();

// 連接到Tomcat

nodeServer.connect(8007, '127.0.0.1', function() {

console.log('CONNECTED');

});

// 存儲客戶端的WebSocket連接實(shí)例

var aSocket = {};

// 同客戶端建立連接

io.sockets.on('connection', function (socketIO) {

// 從客戶端接收數(shù)據(jù),然后發(fā)送至Tomcat

socketIO.on('fromWebClient', function (webClientData) {

// 存儲至映射表

aSocket[socketIO.id] = socketIO;

// 發(fā)送至Tomcat的數(shù)據(jù)中添加socket_id

webClientData['sid'] = socketIO.id;

// 發(fā)送String類型的數(shù)據(jù)至Tomcat

nodeServer.write(JSON.stringify(webClientData));

});

// 客戶端斷開連接

socketIO.on('disconnect', function () {

console.log('DISCONNECTED FROM CLIENT');

});

});

// 從Tomcat接收數(shù)據(jù)

nodeServer.on('data', function (data) {

var jsonData = JSON.parse(data.toString());

// 分發(fā)數(shù)據(jù)至客戶端

for (var i in jsonData.list) {

aSocket[jsonData.list[i]['sid']].emit('pushToWebClient', jsonData.list[i].data);

}

});

上面的代碼省略了一些邏輯,比如Node.js服務(wù)器從Tomcat接收的數(shù)據(jù)分為兩種,一種是推送過來的數(shù)據(jù),另外一種是響應(yīng)請求的數(shù)據(jù),這里統(tǒng)一處理推送過來的數(shù)據(jù)。

在處理通信時(shí),Node.js發(fā)送至Tomcat的數(shù)據(jù)是String格式,而從Tomcat接收的數(shù)據(jù)為Buffer對象(8進(jìn)制),需要轉(zhuǎn)化為String之后再轉(zhuǎn)化為json發(fā)送至客戶端。

本文只是給出一個(gè)這樣兩次連接的簡單例子,具體的業(yè)務(wù)中需要加入許多東西。既然在項(xiàng)目中引入了Node.js,就需要前端承擔(dān)更多的事情,比如對數(shù)據(jù)的處理、緩存、甚至加入很多業(yè)務(wù)邏輯。

總結(jié)

以上是生活随笔為你收集整理的java 推送数据给js,Node.js实现数据推送的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。