麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > HTML > 正文

html5服務(wù)器推送_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

2024-08-26 00:19:45
字體:
供稿:網(wǎng)友

對(duì)于一般的 Web 應(yīng)用開發(fā),大多數(shù)開發(fā)人員并不陌生。在 Web 應(yīng)用中,瀏覽器和服務(wù)器之間使用的是請(qǐng)求 / 響應(yīng)的交互模式。瀏覽器發(fā)出請(qǐng)求,服務(wù)器根據(jù)收到的請(qǐng)求來生成相應(yīng)的響應(yīng)。瀏覽器再對(duì)收到的響應(yīng)進(jìn)行處理,展現(xiàn)給用戶。響應(yīng)的格式可能是 HTML、XML 或 JSON 等。隨著 REST 架構(gòu)風(fēng)格和 AJAX 的流行,服務(wù)器更多地使用 JSON 作為響應(yīng)的數(shù)據(jù)格式。Web 應(yīng)用使用 XMLHttpRequest 對(duì)象來發(fā)送請(qǐng)求,并根據(jù)服務(wù)器端返回的數(shù)據(jù),對(duì)頁面的內(nèi)容進(jìn)行動(dòng)態(tài)更新。通常來說,用戶在頁面上的操作,比如點(diǎn)擊或移動(dòng)鼠標(biāo),會(huì)觸發(fā)相應(yīng)的事件。由 XMLHttpRequest 對(duì)象來發(fā)出請(qǐng)求,得到服務(wù)器響應(yīng)之后進(jìn)行頁面的局部更新。這種方式的不足之處在于:服務(wù)器端產(chǎn)生的數(shù)據(jù)變化不能及時(shí)地通知瀏覽器,而是需要等到下次請(qǐng)求發(fā)出時(shí)才能被瀏覽器獲取。對(duì)于某些對(duì)數(shù)據(jù)實(shí)時(shí)性要求很高的應(yīng)用來說,這種延遲是不能接受的。為了滿足這類應(yīng)用的需求,就需要有某種方式能夠從服務(wù)器端推送數(shù)據(jù)給瀏覽器,以保證服務(wù)器端的數(shù)據(jù)變化可以在第一時(shí)間通知給用戶。目前常見的解決辦法有不少,主要可以分成兩類。這兩類方法的區(qū)別在于是否基于 HTTP 協(xié)議來實(shí)現(xiàn)。不使用 HTTP 協(xié)議的做法是使用 HTML 5 新增的 WebSocket 規(guī)范,而使用 HTTP 協(xié)議的做法則包括簡(jiǎn)易輪詢、COMET 技術(shù)和本文中要介紹的 HTML 5 服務(wù)器推送事件。下面會(huì)對(duì)這幾種技術(shù)進(jìn)行介紹。

簡(jiǎn)介

在介紹 HTML 5 服務(wù)器推送事件之前,首先介紹一些上面提到的幾種服務(wù)器端數(shù)據(jù)推送技術(shù)。第一種是 WebSocket。WebSocket 規(guī)范是 HTML 5 中的一個(gè)重要組成部分,已經(jīng)被很多主流瀏覽器所支持,也有不少基于 WebSocket 開發(fā)的應(yīng)用。正如名稱所表示的一樣,WebSocket 使用的是套接字連接,基于 TCP 協(xié)議。使用 WebSocket 之后,實(shí)際上在服務(wù)器端和瀏覽器之間建立一個(gè)套接字連接,可以進(jìn)行雙向的數(shù)據(jù)傳輸。WebSocket 的功能是很強(qiáng)大的,使用起來也靈活,可以適用于不同的場(chǎng)景。不過 WebSocket 技術(shù)也比較復(fù)雜,包括服務(wù)器端和瀏覽器端的實(shí)現(xiàn)都不同于一般的 Web 應(yīng)用。

除了 WebSocket 之外,其他的實(shí)現(xiàn)方式是基于 HTTP 協(xié)議來達(dá)到實(shí)時(shí)推送的效果。第一種做法是簡(jiǎn)易輪詢,即瀏覽器端定時(shí)向服務(wù)器端發(fā)出請(qǐng)求,來查詢是否有數(shù)據(jù)更新。這種做法比較簡(jiǎn)單,可以在一定程度上解決問題。不過對(duì)于輪詢的時(shí)間間隔需要進(jìn)行仔細(xì)考慮。輪詢的間隔過長(zhǎng),會(huì)導(dǎo)致用戶不能及時(shí)接收到更新的數(shù)據(jù);輪詢的間隔過短,會(huì)導(dǎo)致查詢請(qǐng)求過多,增加服務(wù)器端的負(fù)擔(dān)。

COMET 技術(shù)改進(jìn)了簡(jiǎn)易輪詢的缺點(diǎn),使用的是長(zhǎng)輪詢。長(zhǎng)輪詢的方式在每次請(qǐng)求時(shí),服務(wù)器端會(huì)保持該連接在一段時(shí)間內(nèi)處于打開狀態(tài),而不是在響應(yīng)完成之后就立即關(guān)閉。這樣做的好處是在連接處于打開狀態(tài)的時(shí)間段內(nèi),服務(wù)器端產(chǎn)生的數(shù)據(jù)更新可以被及時(shí)地返回給瀏覽器。當(dāng)上一個(gè)長(zhǎng)連接關(guān)閉之后,瀏覽器會(huì)立即打開一個(gè)新的長(zhǎng)連接來繼續(xù)請(qǐng)求。不過 COMET 技術(shù)的實(shí)現(xiàn)在服務(wù)器端和瀏覽器端都需要第三方庫(kù)的支持。綜合比較上面提到的 4 種不同的技術(shù),簡(jiǎn)易輪詢由于其本身的缺陷,并不推薦使用。COMET 技術(shù)并不是 HTML 5 標(biāo)準(zhǔn)的一部分,從兼容標(biāo)準(zhǔn)的角度出發(fā),也不推薦使用。WebSocket 規(guī)范和服務(wù)器推送技術(shù)都是 HTML 5 標(biāo)準(zhǔn)的組成部分,在主流瀏覽器上都提供了原生的支持,是推薦使用的。不過 WebSocket 規(guī)范更加復(fù)雜一些,適用于需要進(jìn)行復(fù)雜雙向數(shù)據(jù)通訊的場(chǎng)景。對(duì)于簡(jiǎn)單的服務(wù)器數(shù)據(jù)推送的場(chǎng)景,使用服務(wù)器推送事件就足夠了。

在瀏覽器支持方面,服務(wù)器推送事件已經(jīng)在除 IE 外的大部分桌面和移動(dòng)瀏覽器上得到了支持。支持服務(wù)器推送事件的瀏覽器及其版本包括:Firefox 6.0+、Chrome 6.0+、Safari 5.0+、Opera 11.0+、iOS Safari 4.0+、Opera Mobile 11.1+、Chrome for Android 25.0+、Firefox for Android 19.0+ 以及 Blackberry Browser 7.0+ 等。關(guān)于 IE 的支持,在下面的章節(jié)中有詳細(xì)的介紹。

下面對(duì)服務(wù)器推送事件的規(guī)范進(jìn)行具體的說明。

規(guī)范

Server-sent Events 規(guī)范是 HTML 5 規(guī)范的一個(gè)組成部分,具體的規(guī)范文檔見參考資源。該規(guī)范比較簡(jiǎn)單,主要由兩個(gè)部分組成:第一個(gè)部分是服務(wù)器端與瀏覽器端之間的通訊協(xié)議,第二部分則是在瀏覽器端可供 JavaScript 使用的 EventSource 對(duì)象。通訊協(xié)議是基于純文本的簡(jiǎn)單協(xié)議。服務(wù)器端的響應(yīng)的內(nèi)容類型是“text/event-stream”。響應(yīng)文本的內(nèi)容可以看成是一個(gè)事件流,由不同的事件所組成。每個(gè)事件由類型和數(shù)據(jù)兩部分組成,同時(shí)每個(gè)事件可以有一個(gè)可選的標(biāo)識(shí)符。不同事件的內(nèi)容之間通過僅包含回車符和換行符的空行(“/r/n”)來分隔。每個(gè)事件的數(shù)據(jù)可能由多行組成。代碼清單 1 給出了服務(wù)器端響應(yīng)的示例。

服務(wù)器端響應(yīng)的示例

data: first eventdata: second eventid: 100event: myeventdata: third eventid: 101: this is a commentdata: fourth eventdata: fourth event continue

如代碼清單 1 所示,每個(gè)事件之間通過空行來分隔。對(duì)于每一行來說,冒號(hào)(“:”)前面表示的是該行的類型,冒號(hào)后面則是對(duì)應(yīng)的值。可能的類型包括:

  1. 類型為空白,表示該行是注釋,會(huì)在處理時(shí)被忽略。
  2. 類型為 data,表示該行包含的是數(shù)據(jù)。以 data 開頭的行可以出現(xiàn)多次。所有這些行都是該事件的數(shù)據(jù)。
  3. 類型為 event,表示該行用來聲明事件的類型。瀏覽器在收到數(shù)據(jù)時(shí),會(huì)產(chǎn)生對(duì)應(yīng)類型的事件。
  4. 類型為 id,表示該行用來聲明事件的標(biāo)識(shí)符。
  5. 類型為 retry,表示該行用來聲明瀏覽器在連接斷開之后進(jìn)行再次連接之前的等待時(shí)間。

在上面代碼中,第一個(gè)事件只包含數(shù)據(jù)“first event”,會(huì)產(chǎn)生默認(rèn)的事件;第二個(gè)事件的標(biāo)識(shí)符是 100,數(shù)據(jù)為“second event”;第三個(gè)事件會(huì)產(chǎn)生類型為“myevent”的事件;最后一個(gè)事件的數(shù)據(jù)為“fourth event/nfourth event continue”。當(dāng)有多行數(shù)據(jù)時(shí),實(shí)際的數(shù)據(jù)由每行數(shù)據(jù)以換行符連接而成。

如果服務(wù)器端返回的數(shù)據(jù)中包含了事件的標(biāo)識(shí)符,瀏覽器會(huì)記錄最近一次接收到的事件的標(biāo)識(shí)符。如果與服務(wù)器端的連接中斷,當(dāng)瀏覽器端再次進(jìn)行連接時(shí),會(huì)通過 HTTP 頭“Last-Event-ID”來聲明最后一次接收到的事件的標(biāo)識(shí)符。服務(wù)器端可以通過瀏覽器端發(fā)送的事件標(biāo)識(shí)符來確定從哪個(gè)事件開始來繼續(xù)連接。

對(duì)于服務(wù)器端返回的響應(yīng),瀏覽器端需要在 JavaScript 中使用 EventSource 對(duì)象來進(jìn)行處理。EventSource 使用的是標(biāo)準(zhǔn)的事件監(jiān)聽器方式,只需要在對(duì)象上添加相應(yīng)的事件處理方法即可。EventSource 提供了三個(gè)標(biāo)準(zhǔn)事件,如表 1 所示。

表 1. EventSource 對(duì)象提供的標(biāo)準(zhǔn)事件

 

名稱
說明
事件處理方法
open
當(dāng)成功與服務(wù)器建立連接時(shí)產(chǎn)生
onopen
message
當(dāng)收到服務(wù)器發(fā)送的事件時(shí)產(chǎn)生
onmessage
error
當(dāng)出現(xiàn)錯(cuò)誤時(shí)產(chǎn)生
onerror

 

如之前所述,服務(wù)器端可以返回自定義類型的事件。對(duì)于這些事件,可以使用 addEventListener 方法來添加相應(yīng)的事件處理方法。代碼清單 2 給出了 EventSource 對(duì)象的使用示例。

EventSource 對(duì)象的使用示例

var es = new EventSource('events');es.onmessage = function(e) {    console.log(e.data);};es.addEventListener('myevent', function(e) {    console.log(e.data);});

如上所示,在指定 URL 創(chuàng)建出 EventSource 對(duì)象之后,可以通過 onmessage 和 addEventListener 方法來添加事件處理方法。當(dāng)服務(wù)器端有新的事件產(chǎn)生,相應(yīng)的事件處理方法會(huì)被調(diào)用。EventSource 對(duì)象的 onmessage 屬性的作用類似于 addEventListener( ‘ message ’ ),不過 onmessage 屬性只支持一個(gè)事件處理方法。在介紹完服務(wù)器推送事件的規(guī)范內(nèi)容之后,下面介紹服務(wù)器端的實(shí)現(xiàn)。

服務(wù)器端和瀏覽器端實(shí)現(xiàn)

從上一節(jié)中對(duì)通訊協(xié)議的描述可以看出,服務(wù)器端推送事件是一個(gè)比較簡(jiǎn)單的協(xié)議。服務(wù)器端的實(shí)現(xiàn)也相對(duì)比較簡(jiǎn)單,只需要按照協(xié)議規(guī)定的格式,返回響應(yīng)內(nèi)容即可。在開源社區(qū)可以找到各種不同的服務(wù)器端技術(shù)相對(duì)應(yīng)的實(shí)現(xiàn)。自己開發(fā)的難度也不大。本文使用 Java 作為服務(wù)器端的實(shí)現(xiàn)語言。相應(yīng)的實(shí)現(xiàn)基于開源的 jetty-eventsource-servlet 項(xiàng)目,見參考資源。下面通過一個(gè)具體的示例來說明如何使用 jetty-eventsource-servlet 項(xiàng)目。示例用來模擬一個(gè)物體在某個(gè)限定空間中的隨機(jī)移動(dòng)。該物體從一個(gè)隨機(jī)位置開始,然后從上、下、左和右四個(gè)方向中隨機(jī)選擇一個(gè)方向,并在該方向上移動(dòng)隨機(jī)的距離。服務(wù)器端不斷改變?cè)撐矬w的位置,并把位置信息推送給瀏覽器,由瀏覽器來顯示。

服務(wù)器端實(shí)現(xiàn)

服務(wù)器端的實(shí)現(xiàn)由兩部分組成:一部分是用來產(chǎn)生數(shù)據(jù)的 org.eclipse.jetty.servlets.EventSource 接口的實(shí)現(xiàn),另一部分是作為瀏覽器訪問端點(diǎn)的繼承自 org.eclipse.jetty.servlets.EventSourceServlet 類的 servlet 實(shí)現(xiàn)。下面代碼給出了 EventSource 接口的實(shí)現(xiàn)類。

EventSource 接口的實(shí)現(xiàn)類 MovementEventSource

 public class MovementEventSource implements EventSource {  private int width = 800; private int height = 600; private int stepMax = 5; private int x = 0; private int y = 0; private Random random = new Random(); private Logger logger = Logger.getLogger(getClass().getName());  public MovementEventSource(int width, int height, int stepMax) {  this.width = width;  this.height = height;  this.stepMax = stepMax;  this.x = random.nextInt(width);  this.y = random.nextInt(height); } @Override public void onOpen(Emitter emitter) throws IOException {  query(emitter); //開始生成位置信息 } @Override public void onResume(Emitter emitter, String lastEventId)   throws IOException {  updatePosition(lastEventId); //更新起始位置  query(emitter);  //開始生成位置信息 }  //根據(jù)Last-Event-Id來更新起始位置 private void updatePosition(String id) {  if (id != null) {   String[] pos = id.split(",");   if (pos.length > 1) {    int xPos = -1, yPos = -1;    try {     xPos = Integer.parseInt(pos[0], 10);     yPos = Integer.parseInt(pos[1], 10);    } catch (NumberFormatException e) {         }    if (isValidMove(xPos, yPos)) {     x = xPos;     y = yPos;    }   }  } }  private void query(Emitter emitter) throws IOException {  emitter.comment("Start sending movement information.");  while(true) {   emitter.comment("");   move(); //移動(dòng)位置   String id = String.format("%s,%s", x, y);   emitter.id(id); //根據(jù)位置生成事件標(biāo)識(shí)符   emitter.data(id); //發(fā)送位置信息數(shù)據(jù)   try {    Thread.sleep(2000);   } catch (InterruptedException e) {    logger.log(Level.WARNING, /               "Movement query thread interrupted. Close the connection.", e);    break;   }  }  emitter.close(); //當(dāng)循環(huán)終止時(shí),關(guān)閉連接 } @Override public void onClose() {   }  //獲取下一個(gè)合法的移動(dòng)位置 private void move() {  while (true) {   int[] move = getMove();   int xNext = x + move[0];   int yNext = y + move[1];   if (isValidMove(xNext, yNext)) {    x = xNext;    y = yNext;    break;   }  } } //判斷當(dāng)前的移動(dòng)位置是否合法 private boolean isValidMove(int x, int y) {  return x >= 0 && x <= width && y >=0 && y <= height; }  //隨機(jī)生成下一個(gè)移動(dòng)位置 private int[] getMove() {  int[] xDir = new int[] {-1, 0, 1, 0};  int[] yDir = new int[] {0, -1, 0, 1};  int dir = random.nextInt(4);  return new int[] {xDir[dir] * random.nextInt(stepMax), /     yDir[dir] * random.nextInt(stepMax)}; }}

類 MovementEventSource 需要實(shí)現(xiàn) EventSource 接口的 onOpen、onResume 和 onClose 方法,其中 onOpen 方法在瀏覽器端的連接打開的時(shí)候被調(diào)用,onResume 方法在瀏覽器端重新建立連接時(shí)被調(diào)用,onClose 方法則在瀏覽器關(guān)閉連接的時(shí)候被調(diào)用。onOpen 和 onResume 方法都有一個(gè) EventSource.Emitter 接口類型的參數(shù),可以用來發(fā)送數(shù)據(jù)。EventSource.Emitter 接口中包含的方法包括 data、event、comment、id 和 close 等,分別對(duì)應(yīng)于通訊協(xié)議中各種不同類型的事件。而 onResume 方法還額外包含一個(gè)參數(shù) lastEventId,表示通過 Last-Event-ID 頭發(fā)送過來的最近一次事件的標(biāo)識(shí)符。

MovementEventSource 類中事件生成的主要邏輯在 query 方法中。該方法中包含一個(gè)無限循環(huán),每隔 2 秒鐘改變一次位置,同時(shí)把更新之后的位置通過 EventSource.Emitter 接口的 data 方法發(fā)送給瀏覽器端。每個(gè)事件都有對(duì)應(yīng)的標(biāo)識(shí)符,而標(biāo)識(shí)符的值就是位置本身。如果連接斷開之后,瀏覽器重新進(jìn)行連接,可以從上一次的位置開始繼續(xù)移動(dòng)該物體。

與 MovementEventSource 類對(duì)應(yīng)的 servlet 實(shí)現(xiàn)比較簡(jiǎn)單,只需要繼承自 EventSourceServlet 類并覆寫 newEventSource 方法即可。在 newEventSource 方法的實(shí)現(xiàn)中,需要返回一個(gè) MovementEventSource 類的對(duì)象,如下所示。每當(dāng)瀏覽器端建立連接時(shí),該 servlet 會(huì)創(chuàng)建一個(gè)新的 MovementEventSource 類的對(duì)象來處理該請(qǐng)求。

servlet 實(shí)現(xiàn)類 MovementServlet

 public class MovementServlet extends EventSourceServlet {  @Override  protected EventSource newEventSource(HttpServletRequest request,  String clientId) {  return new MovementEventSource(800, 600, 20);  }  }

在服務(wù)器端實(shí)現(xiàn)中,需要注意的是要添加相應(yīng)的 servlet 過濾器支持。這是 jetty-eventsource-servlet 項(xiàng)目所依賴的 Jetty Continuations 框架的要求,否則的話會(huì)出現(xiàn)錯(cuò)誤。添加過濾器的方式是在 web.xml 文件中添加代碼如下所示的配置內(nèi)容。

Jetty Continuations 所需 servlet 過濾器的配置

 <filter>     <filter-name>continuation</filter-name>     <filter-class>org.eclipse.jetty.continuation.ContinuationFilter</filter-class>  </filter>  <filter-mapping>     <filter-name>continuation</filter-name>     <url-pattern>/sse/*</url-pattern>  </filter-mapping>

瀏覽器端實(shí)現(xiàn)

瀏覽器端的實(shí)現(xiàn)也比較簡(jiǎn)單,只需要?jiǎng)?chuàng)建出 EventSource 對(duì)象,并添加相應(yīng)的事件處理方法即可。下面代碼給出了相應(yīng)的實(shí)現(xiàn)。在頁面中使用一個(gè)方塊表示物體。當(dāng)接收到新的事件時(shí),根據(jù)事件數(shù)據(jù)中給出的坐標(biāo)信息,更新方塊在頁面上的位置。

瀏覽器端的實(shí)現(xiàn)代碼

 var es = new EventSource('sse/movement');  es.addEventListener('message', function(e) {      var pos = e.data.split(','), x = pos[0], y = pos[1];      $('#box').css({          left : x + 'px',          top : y + 'px'          });      });

在介紹完基本的服務(wù)器端和瀏覽器端實(shí)現(xiàn)之后,下面介紹比較重要的 IE 的支持。

IE 支持

使用瀏覽器原生的 EventSource 對(duì)象的一個(gè)比較大的問題是 IE 并不提供支持。為了在 IE 上提供同樣的支持,一般有兩種辦法。第一種辦法是在其他瀏覽器上使用原生 EventSource 對(duì)象,而在 IE 上則使用簡(jiǎn)易輪詢或 COMET 技術(shù)來實(shí)現(xiàn);另外一種做法是使用 polyfill 技術(shù),即使用第三方提供的 JavaScript 庫(kù)來屏蔽瀏覽器的不同。本文使用的是 polyfill 技術(shù),只需要在頁面中加載第三方 JavaScript 庫(kù)即可。應(yīng)用本身的瀏覽器端代碼并不需要進(jìn)行改動(dòng)。一般推薦使用第二種做法,因?yàn)檫@樣的話,在服務(wù)器端只需要使用一種實(shí)現(xiàn)技術(shù)即可。

在 IE 上提供類似原生 EventSource 對(duì)象的實(shí)現(xiàn)并不簡(jiǎn)單。理論上來說,只需要通過 XMLHttpRequest 對(duì)象來獲取服務(wù)器端的響應(yīng)內(nèi)容,并通過文本解析,就可以提取出相應(yīng)的事件,并觸發(fā)對(duì)應(yīng)的事件處理方法。不過問題在于 IE 上的 XMLHttpRequest 對(duì)象并不支持獲取部分的響應(yīng)內(nèi)容。只有在響應(yīng)完成之后,才能獲取其內(nèi)容。由于服務(wù)器端推送事件使用的是一個(gè)長(zhǎng)連接。當(dāng)連接一直處于打開狀態(tài)時(shí),通過 XMLHttpRequest 對(duì)象并不能獲取響應(yīng)的內(nèi)容,也就無法觸發(fā)對(duì)應(yīng)的事件。更具體的來說,當(dāng) XMLHttpRequest 對(duì)象的 readyState 為 3(READYSTATE_INTERACTIVE)時(shí),其 responseText 屬性是無法獲取的。

為了解決 IE 上 XMLHttpRequest 對(duì)象的問題,就需要使用 IE 8 中引入的 XDomainRequest 對(duì)象。XDomainRequest 對(duì)象的作用是發(fā)出跨域的 AJAX 請(qǐng)求。XDomainRequest 對(duì)象提供了 onprogress 事件。當(dāng) onprogress 事件發(fā)生時(shí),可以通過 responseText 屬性來獲取到響應(yīng)的部分內(nèi)容。這是 XDomainRequest 對(duì)象和 XMLHttpRequest 對(duì)象的最大不同,也是使用 XDomainRequest 對(duì)象來實(shí)現(xiàn)類似原生 EventSource 對(duì)象的基礎(chǔ)。在使用 XDomainRequest 對(duì)象打開與服務(wù)器端的連接之后,當(dāng)服務(wù)器端有新的數(shù)據(jù)產(chǎn)生時(shí),可以通過 XDomainRequest 對(duì)象的 onprogress 事件的處理方法來進(jìn)行處理,對(duì)接收到的數(shù)據(jù)進(jìn)行解析,根據(jù)數(shù)據(jù)的內(nèi)容觸發(fā)相應(yīng)的事件。

不過由于 XDomainRequest 對(duì)象本來的目的是發(fā)出跨域 AJAX 請(qǐng)求,考慮到跨域訪問的安全性問題,XDomainRequest 對(duì)象在使用時(shí)的限制也比較嚴(yán)格。這些限制會(huì)影響到其作為 EventSource 對(duì)象的實(shí)現(xiàn)方式。具體的限制和解決辦法如下所示:

  1. 服務(wù)器端的響應(yīng)需要包含 Access-Control-Allow-Origin 頭,用來聲明允許從哪些域訪問該 URL。“*”表示允許來自任何域的訪問,不推薦使用該值。一般使用與當(dāng)前應(yīng)用相同的域,限制只允許來自當(dāng)前域的訪問。
  2. XDomainRequest 對(duì)象發(fā)出的請(qǐng)求不能包含自定義的 HTTP 頭,這就限制了不能使用 Last-Event-ID 頭來聲明瀏覽器端最近一次接收到的事件的標(biāo)識(shí)符。只能通過 HTTP 請(qǐng)求的其他方式來傳遞該標(biāo)識(shí)符,如 GET 請(qǐng)求的參數(shù)或 POST 請(qǐng)求的內(nèi)容體。
  3. XDomainRequest 對(duì)象的請(qǐng)求的內(nèi)容類型(Content-Type)只能是“text/plain”。這就意味著,當(dāng)使用 POST 請(qǐng)求時(shí),服務(wù)器端使用的框架,如 servlet,不會(huì)對(duì) POST 請(qǐng)求的內(nèi)容進(jìn)行自動(dòng)解析,無法使用 HttpServletRequest 類的 getParameter 方法來獲取 POST 請(qǐng)求的內(nèi)容。只能在服務(wù)器端對(duì)原始的請(qǐng)求內(nèi)容進(jìn)行解析,獲取到其中的參數(shù)的值。
  4. XDomainRequest 對(duì)象發(fā)出的請(qǐng)求中不包含任何與用戶認(rèn)證相關(guān)的信息,包括 cookie 等。這就意味著,如果服務(wù)器端需要認(rèn)證,則需要通過 HTTP 請(qǐng)求的其他方式來傳遞用戶的認(rèn)證信息,比如 session 的 ID 等。

由于 XDomainRequest 對(duì)象的這些限制,服務(wù)器端的實(shí)現(xiàn)也需要作出相應(yīng)的改動(dòng)。這些改動(dòng)包括返回 Access-Control-Allow-Origin 頭;對(duì)于瀏覽器端發(fā)送的“text/plain”類型的參數(shù)進(jìn)行解析;處理請(qǐng)求中包含的用戶認(rèn)證相關(guān)的信息。

本文的示例使用的 polyfill 庫(kù)是 GitHub 上的 Yaffle 開發(fā)的 EventSource 項(xiàng)目,具體的地址見參考資源。在使用該 polyfill 庫(kù),并對(duì)服務(wù)器端的實(shí)現(xiàn)進(jìn)行修改之后,就可以在 IE 8 及以上的瀏覽器中使用服務(wù)器推送事件。如果需要支持 IE 7,則只能使用簡(jiǎn)易輪詢或 COMET 技術(shù)。本文的示例代碼見參考資源。

小結(jié)

如果需要從服務(wù)器端推送數(shù)據(jù)給瀏覽器,可以使用的基于 HTML 5 規(guī)范標(biāo)準(zhǔn)的技術(shù)包括 WebSocket 和服務(wù)器推送事件。開發(fā)人員可以根據(jù)應(yīng)用的具體需求來選擇合適的技術(shù)。如果只是需要從服務(wù)器端推送數(shù)據(jù),服務(wù)器推送事件的規(guī)范更加簡(jiǎn)單,實(shí)現(xiàn)起來更容易。本文對(duì)服務(wù)器推送事件的規(guī)范內(nèi)容、服務(wù)器端和瀏覽器端的實(shí)現(xiàn)都進(jìn)行了詳細(xì)的介紹,對(duì)如何支持 IE 瀏覽器也進(jìn)行了具體的分析。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到HTML教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 一区二区网 | 免费国产在线精品 | 97青青草视频 | 国产精品色综合 | 永久免费黄色大片 | 最新欧美精品一区二区三区 | 依人在线视频 | 亚洲少妇诱惑 | 91美女视频在线 | 久久久久久久一区 | 黄在线免费 | h视频免费在线观看 | 国产精品嘿咻嘿咻在线播放 | 视频一区二区三区视频 | 久久久aa| 国产美女一区二区在线观看 | 成人在线视频在线观看 | 亚洲午夜激情网 | 91成人一区| 成人在线视频播放 | 一日本道久久久精品国产 | 欧美日韩在线视频一区二区 | 在线成人亚洲 | 久久96国产精品久久秘臀 | 成人一级视频 | 中国老女人一级毛片视频 | 久久国产91| 久久综合网址 | 国产精品1区| 日韩高清影视 | 99这里有精品 | 亚洲福利在线观看视频 | 在线看一区二区三区 | 色日本视频 | www.99re14.com| 羞羞视频免费网站男男 | 国产免费一区二区三区最新不卡 | h久久| 男女污视频在线观看 | 国产精品无码久久久久 | 九九热精品视频在线 |