中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

反向Ajax的示例分析

發布時間:2021-09-14 13:50:07 來源:億速云 閱讀:162 作者:小新 欄目:web開發

這篇文章主要為大家展示了“反向Ajax的示例分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“反向Ajax的示例分析”這篇文章吧。

場景1:當有新郵件的時候,網頁自動彈出提示信息而無需用戶手動的刷新收件箱。

場景2:當用戶的手機掃描完成頁面中的二維碼以后,頁面會自動跳轉。

場景3:在類似聊天室的環境中有任何人發言,所有登錄用戶都可以即時看見信息。

與傳統的MVC模型請求必須從客戶端發起由服務器響應相比,使用反向Ajax能夠模擬服務器端主動向客戶端推送事件從而提高用戶體驗。本文將分兩個部分討論反向Ajax技術,包括:Comet和WebSocket。文章旨在演示如何實現以上兩種技術手段,Struts2或SpringMVC中的應用并未涉及。此外,Servlet的配置也采用注解的方式,相關知識大家可以參考其它資料。

一、Comet(最佳的兼容手段)

Comet本質上則是這樣的一種概念:能夠從服務器端向客戶端發送數據。在一個標準的 HTTP Ajax 請求中,數據是發送給服務器端的,反向 Ajax 以某些特定的方式來模擬發出一個 Ajax 請求,這樣的話,服務器就可以盡可能快地向客戶端發送事件。由于普通HTTP請求往往會伴隨頁面的跳轉,而推送事件則需要瀏覽器停留在同一個頁面或者框架下,因此Comet的實現只能夠通過Ajax來完成。

反向Ajax的示例分析

它的實現過程如下:頁面加載的時候隨即向服務器發送一條Ajax請求,服務器端獲取請求并將它保存在一個線程安全的容器中(通常為隊列)。同時服務器端仍然可以正常響應其他請求。當需要推送的事件到來的時候,服務器遍歷容器中的請求在返回應答后刪除。于是所有停留在頁面中的瀏覽器都會獲得該應答,并再次發送Ajax請求,重復上述過程。

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE html>
<html lang="en">
<base href="<%=basePath%>">
<head>
<title>WebSocket</title>
<script type="text/javascript" src="static/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$(function() {
connect();
$("#btn").click(function() {
var value = $("#message").val();
$.ajax({
url : "longpolling?method=onMessage&msg=" + value,
cache : false,
dataType : "text",
success : function(data) {
}
});
});
});
function connect() {
$.ajax({
url : "longpolling?method=onOpen",
cache : false,
dataType : "text",
success : function(data) {
connect();
alert(data);
}
});
}
</script>
</head>
<body>
<h2>LongPolling</h2>
<input type="text" id="message" />
<input type="button" id="btn" value="發送" />
</body>
</html>

我們注意到,由btn發送的請求其實并不需要獲取應答。整個過程的關鍵是需要客戶端始終讓服務器保持connect()的請求。而服務器端首先需要支持這種異步的響應方式,幸運的是目前為止絕大部分的Servlet容器都已經提供了良好的支持。下面以Tomcat為例:

package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(value="/longpolling", asyncSupported=true)
public class Comet extends HttpServlet {
private static final Queue<AsyncContext> CONNECTIONS = new ConcurrentLinkedQueue<AsyncContext>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if (method.equals("onOpen")) {
onOpen(req, resp);
} else if (method.equals("onMessage")) {
onMessage(req, resp);
}
}
private void onOpen(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AsyncContext context = req.startAsync();
context.setTimeout(0);
CONNECTIONS.offer(context);
}
private void onMessage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = req.getParameter("msg");
broadcast(msg);
}
private synchronized void broadcast(String msg) {
for (AsyncContext context : CONNECTIONS) {
HttpServletResponse response = (HttpServletResponse) context.getResponse();
try {
PrintWriter out = response.getWriter();
out.print(msg);
out.flush();
out.close();
context.complete();
CONNECTIONS.remove(context);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

ConcurrentLinkedQueue是Queue隊列的一個線程安全實現,這里使用它來作為保存請求的容器。AsyncContext是Tomcat支持的異步環境,不同的服務器使用的對象也略有不同。Jetty支持的對象是Continuation。完成了廣播的請求需要通過context.complete()將相關請求結束,并使用CONNECTIONS.remove(context)刪除隊列。

二、WebSocket(來自HTML5的支持)

使用 HTTP 長輪詢的 Comet 是可靠地實現反向 Ajax 的最佳方式,因為現在所有瀏覽器都提供了這方面的支持。

WebSockets 在 HTML5 中出現,是比 Comet 更新的反向 Ajax 技術。WebSockets 支持雙向、全雙工通信信道,而且許多瀏覽器(Firefox、Google Chrome 和 Safari)也支持它。連接通過 HTTP 請求(也稱為 WebSockets 握手)和一些特殊的標頭 (header)。連接一直處于激活狀態,您可以用 JavaScript 編寫和接收數據,正如您使用原始 TCP 套接字一樣。

通過輸入 ws:// 或 wss://(在 SSL 上)啟動 WebSocket URL。如圖:

反向Ajax的示例分析

首先:WebSockets并非在所有瀏覽器上都能獲得良好的支持,顯然IE又拖了后腿。因此當你打算使用這項技術之前必須考慮到用戶的使用環境,如果你的項目面向的是互聯網或者包括手機端用戶,奉勸大家三思。

其次:WebSockets提供的請求區別于普通的HTTP請求,它是一種全雙工通信且始終處于激活狀態(如果你不去關閉它的話)。這就意味著你不用每次獲得應答后再次向服務器發送請求,這樣可以節約大量的資源。

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
String ws = "ws://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE html>
<html lang="en">
<base href="<%=basePath%>">
<head>
<title>WebSocket</title>
<script type="text/javascript" src="static/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$(function() {
var websocket = null;
if ("WebSocket" in window){
websocket = new WebSocket("<%=ws%>websocket");
} else {
alert("not support");
}
websocket.onopen = function(evt) {
}
websocket.onmessage = function(evt) {
alert(evt.data);
}
websocket.onclose = function(evt) {
}
$("#btn").click(function() {
var text = $("#message").val();
websocket.send(text);
});
});
</script>
</head>
<body>
<h2>WebSocket</h2>
<input type="text" id="message" />
<input type="button" id="btn" value="發送"/>
</body>
</html>

JQuery對WebSocket還未提供更良好的支持,因此我們必須使用Javascript來編寫部分代碼(好在并不復雜)。并且打部分常見的服務器都可以支持ws請求,以Tomcat為例。在6.0版本中WebSocketServlet對象已經被標注為@java.lang.Deprecated,7.0以后的版本支持jsr365提供的實現,因此你必須使用注解來完成相關配置。

package servlet;
import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/websocket")
public class WebSocket {
private static final Queue<WebSocket> CONNECTIONS = new ConcurrentLinkedQueue<WebSocket>();
private Session session;
@OnOpen
public void onOpen(Session session) {
this.session = session;
CONNECTIONS.offer(this);
}
@OnMessage
public void onMessage(String message) {
broadcast(message);
}
@OnClose
public void onClose() {
CONNECTIONS.remove(this);
}
private synchronized void broadcast(String msg) {
for (WebSocket point : CONNECTIONS) {
try {
point.session.getBasicRemote().sendText(msg);
} catch (IOException e) {
CONNECTIONS.remove(point);
try {
point.session.close();
} catch (IOException e1) {
}
}
}
}
}

三、總結(從請求到推送)

在傳統通信方案中,如果系統 A 需要系統 B 中的信息,它會向系統 B 發送一個請求。系統 B 將處理請求,而系統 A 會等待響應。處理完成后,會將響應發送回系統 A。在同步 通信模式下,資源使用效率比較低,這是因為等待響應時會浪費處理時間。

在異步 模式下,系統 A 將訂閱它想從系統 B 中獲取的信息。然后,系統 A 可以向系統 B 發送一個通知,也可以立即返回信息,與此同時,系統 A 可以處理其他事務。這個步驟是可選的。在事件驅動應用程序中,通常不必請求其他系統發送事件,因為您不知道這些事件是什么。在系統 B 發布響應之后,系統 A 會立即收到該響應。

Web 框架過去通常依賴傳統 “請求-響應” 模式,該模式會導致頁面刷新。隨著 Ajax、Reverse Ajax 以及 WebSocket 的出現,現在可以將事件驅動架構的概念輕松應用于 Web,獲得去耦合、可伸縮性和反應性 (reactivity) 等好處。更良好的用戶體驗也會帶來新的商業契機。

以上是“反向Ajax的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

云林县| 曲水县| 页游| 彰武县| 巍山| 綦江县| 阳曲县| 利津县| 阿拉善右旗| 武山县| 营口市| 凤庆县| 渭源县| 手游| 乐平市| 若尔盖县| 体育| 隆德县| 宝清县| 方山县| 肃南| 深水埗区| 汽车| 塘沽区| 岚皋县| 蒙山县| 东阿县| 铜陵市| 浙江省| 房山区| 耒阳市| 二连浩特市| 察哈| 赣榆县| 镇远县| 龙泉市| 团风县| 泾源县| 鄂托克旗| 广州市| 申扎县|