Heim  >  Artikel  >  Web-Frontend  >  Meistere den Rückschlag gegen Ajax in 30 Minuten

Meistere den Rückschlag gegen Ajax in 30 Minuten

亚连
亚连Original
2018-05-23 15:49:481522Durchsuche

In diesem Artikel werden hauptsächlich relevante Informationen zu Reverse Ajax vorgestellt, die in 30 Minuten schnell erlernt werden können. Freunde, die sie benötigen, können darauf verweisen

Szenario 1: Wenn eine neue E-Mail vorliegt, wird die Webseite automatisch angezeigt Es erscheint eine Aufforderungsnachricht, ohne dass der Benutzer Ihren Posteingang manuell aktualisieren muss.

Szenario 2: Nachdem das Mobiltelefon des Benutzers den QR-Code auf der Seite gescannt hat, springt die Seite automatisch weiter.

Szenario 3: Wenn jemand in einer Chatroom-ähnlichen Umgebung spricht, können alle angemeldeten Benutzer die Nachricht sofort sehen.

Im Vergleich zum herkömmlichen MVC-Modell, bei dem Anfragen vom Client initiiert und vom Server beantwortet werden müssen, kann die Verwendung von Reverse Ajax simulieren, dass der Server Ereignisse aktiv an den Client weiterleitet, um die Benutzererfahrung zu verbessern. In diesem Artikel wird die umgekehrte Ajax-Technologie in zwei Teilen erläutert, darunter: Comet und WebSocket. Der Artikel soll zeigen, wie die beiden oben genannten technischen Mittel implementiert werden. Die Anwendung in Struts2 oder SpringMVC wird nicht behandelt. Darüber hinaus verwendet die Servlet-Konfiguration auch Anmerkungen. Weitere Informationen finden Sie in anderen Materialien.

1. Comet (die beste Kompatibilitätsmethode)

Comet ist im Wesentlichen ein Konzept: die Möglichkeit, eine Verbindung vom Server zum Client herzustellen Daten. Bei einer Standard-HTTP-Ajax-Anfrage werden Daten an den Server gesendet. Reverse Ajax simuliert das Senden einer Ajax-Anfrage auf bestimmte Weise, sodass der Server Ereignisse so schnell wie möglich an den Client senden kann. Da normale HTTP-Anfragen häufig von Seitensprüngen begleitet werden und Push-Ereignisse erfordern, dass der Browser auf derselben Seite oder demselben Frame bleibt, kann die Implementierung von Comet nur über Ajax abgeschlossen werden.

Der Implementierungsprozess ist wie folgt: Wenn die Seite geladen wird, wird eine Ajax-Anfrage an den Server gesendet, und der Server erhält die Anfrage und speichert sie in einem Thread. sicherer Container (normalerweise für die Warteschlange). Gleichzeitig kann der Server weiterhin normal auf andere Anfragen reagieren. Wenn das Ereignis eintrifft, das gepusht werden muss, durchläuft der Server die Anforderungen im Container und löscht ihn, nachdem er die Antwort zurückgegeben hat. Dann erhalten alle Browser, die auf der Seite bleiben, die Antwort und senden erneut Ajax-Anfragen, wobei der obige Vorgang wiederholt wird.

<%@ 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>
<h1>LongPolling</h1>
<input type="text" id="message" />
<input type="button" id="btn" value="发送" />
</body>
</html>

Uns ist aufgefallen, dass die von btn gesendete Anfrage eigentlich keiner Antwort bedarf. Der Schlüssel zum gesamten Prozess besteht darin, dass der Client immer verlangt, dass der Server weiterhin connect()-Anfragen stellt. Die Serverseite muss diese asynchrone Antwortmethode zunächst unterstützen. Glücklicherweise bieten die meisten Servlet-Container bisher eine gute Unterstützung. Nehmen Sie Tomcat unten als Beispiel:

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 ist eine threadsichere Implementierung der Queue-Warteschlange, die hier als Container zum Speichern von Anforderungen verwendet wird. AsyncContext ist eine von Tomcat unterstützte asynchrone Umgebung, und verschiedene Server verwenden leicht unterschiedliche Objekte. Das von Jetty unterstützte Objekt ist Continuation. Die Anforderung, die die Übertragung abgeschlossen hat, muss die zugehörige Anforderung über context.complete() beenden und CONNECTIONS.remove(context) verwenden, um die Warteschlange zu löschen.

2. WebSocket (Unterstützung von HTML5)

Comet mit HTTP Long Polling ist der beste Weg, um die umgekehrte Ajax-Methode zuverlässig zu implementieren, weil alle Browser unterstützen dies mittlerweile.

WebSockets erschienen in HTML5 und sind eine neuere Reverse-Ajax-Technologie als Comet. WebSockets unterstützen einen bidirektionalen Vollduplex-Kommunikationskanal, der auch von vielen Browsern (Firefox, Google Chrome und Safari) unterstützt wird. Verbindungen werden über HTTP-Anfragen (auch WebSockets-Handshakes genannt) und einige spezielle Header hergestellt. Die Verbindung ist immer aktiv und Sie können Daten in JavaScript schreiben und empfangen, genau wie mit einem unformatierten TCP-Socket.

Starten Sie die WebSocket-URL, indem Sie ws:// oder wss:// (über SSL) eingeben. Wie im Bild gezeigt:

Zunächst einmal: WebSockets werden nicht von allen Browsern gut unterstützt und der IE hält sich offensichtlich zurück. Wenn Sie diese Technologie verwenden möchten, müssen Sie daher die Nutzungsumgebung des Benutzers berücksichtigen. Wenn Ihr Projekt für das Internet gedacht ist oder Mobiltelefonbenutzer einschließt, rate ich jedem, zweimal darüber nachzudenken.

Zweitens: Die von WebSockets bereitgestellte Anfrage unterscheidet sich von einer normalen HTTP-Anfrage. Es handelt sich um eine Vollduplex-Kommunikation und ist immer aktiv (sofern Sie sie nicht deaktivieren). Dies bedeutet, dass Sie nicht jedes Mal, wenn Sie eine Antwort erhalten, erneut eine Anfrage an den Server senden müssen, was viele Ressourcen sparen kann.

<%@ 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>
<h1>WebSocket</h1>
<input type="text" id="message" />
<input type="button" id="btn" value="发送"/>
</body>
</html>

JQuery bietet noch keine bessere Unterstützung für WebSocket, daher müssen wir Javascript verwenden, um einen Teil des Codes zu schreiben (zum Glück ist es nicht kompliziert). Und einige gängige Server können WS-Anfragen unterstützen, am Beispiel von Tomcat. In Version 6.0 wurde das WebSocketServlet-Objekt als @java.lang.Deprecated markiert. Versionen nach 7.0 unterstützen die von jsr365 bereitgestellte Implementierung, daher müssen Sie Anmerkungen verwenden, um relevante Konfigurationen abzuschließen.

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) {
}
}
}
}
}

3. Zusammenfassung (von der Anfrage bis zum Push)

Wenn System A in einem herkömmlichen Kommunikationsschema Informationen von System B benötigt, sendet es eine Anfrage an System B. System B bearbeitet die Anfrage, während System A auf die Antwort wartet. Sobald die Verarbeitung abgeschlossen ist, wird die Antwort an System A zurückgesendet. Im synchronen Kommunikationsmodus ist die Ressourcennutzung weniger effizient, da Verarbeitungszeit beim Warten auf eine Antwort verschwendet wird.

Im asynchronen Modus abonniert System A die Informationen, die es von System B erhalten möchte. System A kann dann eine Benachrichtigung an System B senden oder die Informationen sofort zurücksenden, während System A andere Transaktionen abwickeln kann. Dieser Schritt ist optional. In einer ereignisgesteuerten Anwendung müssen Sie andere Systeme normalerweise nicht zum Senden von Ereignissen auffordern, da Sie nicht wissen, um welche Ereignisse es sich handelt. System A erhält die Antwort sofort, nachdem System B sie veröffentlicht hat.

Web-Frameworks basierten früher auf dem traditionellen „Request-Response“-Modell, was zu einer Seitenaktualisierung führte. Mit dem Aufkommen von Ajax, Reverse Ajax und WebSocket ist es nun möglich, die Konzepte der ereignisgesteuerten Architektur problemlos auf das Web anzuwenden und dabei die Vorteile der Entkopplung, Skalierbarkeit und Reaktivität zu nutzen. Eine bessere Benutzererfahrung wird auch neue Geschäftsmöglichkeiten mit sich bringen.

Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.

Verwandte Artikel:

Ajax implementiert intelligente Eingabeaufforderungssuchfunktion

Öffnen Sie eine neue Fensteradresse, nachdem die Ajax-Anfrage erfolgreich ist

Ajax verwenden, um asynchrone Aktualisierungsanforderungen zu implementieren

Das obige ist der detaillierte Inhalt vonMeistere den Rückschlag gegen Ajax in 30 Minuten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn