Maison > Article > interface Web > Maîtrisez l’Ajax inversé en 30 minutes
Cet article présente principalement les informations pertinentes sur l'Ajax inversé qui peuvent être maîtrisées rapidement en 30 minutes. Les amis qui en ont besoin peuvent s'y référer
Scénario 1 : Lorsqu'il y a un nouvel e-mail, la page Web s'ouvre automatiquement. fait apparaître un message d'invite sans que l'utilisateur ait besoin d'actualiser manuellement votre boîte de réception.
Scénario 2 : Une fois que le téléphone mobile de l'utilisateur a scanné le code QR sur la page, la page sautera automatiquement.
Scénario 3 : si quelqu'un parle dans un environnement de type salon de discussion, tous les utilisateurs connectés peuvent voir le message immédiatement.
Par rapport au modèle MVC traditionnel où les requêtes doivent être initiées par le client et auxquelles le serveur doit répondre, l'utilisation d'Ajax inversé peut simuler le serveur qui envoie activement des événements au client pour améliorer l'expérience utilisateur. Cet article abordera la technologie Ajax inversée en deux parties, notamment : Comet et WebSocket. L'article vise à démontrer comment implémenter les deux moyens techniques ci-dessus, et l'application dans Struts2 ou SpringMVC n'est pas couverte. De plus, la configuration du servlet utilise également des annotations. Pour des connaissances pertinentes, vous pouvez vous référer à d'autres documents.
1. Comet (la meilleure méthode de compatibilité)
Comet est essentiellement un concept : pouvoir se connecter depuis le serveur au client envoie données. Dans une requête HTTP Ajax standard, les données sont envoyées au serveur. Reverse Ajax simule l'exécution d'une requête Ajax d'une manière spécifique, afin que le serveur puisse envoyer des événements au client le plus rapidement possible. Étant donné que les requêtes HTTP ordinaires sont souvent accompagnées de sauts de page et que les événements push nécessitent que le navigateur reste sur la même page ou cadre, l'implémentation de Comet ne peut être réalisée que via Ajax.
Son processus de mise en œuvre est le suivant : lorsque la page est chargée, une requête Ajax est envoyée au serveur, et le serveur récupère la requête et l'enregistre dans un thread- conteneur sécurisé (généralement pour la file d'attente). Dans le même temps, le serveur peut toujours répondre normalement aux autres demandes. Lorsque l'événement qui doit être poussé arrive, le serveur parcourt les requêtes dans le conteneur et le supprime après avoir renvoyé la réponse. Ensuite, tous les navigateurs restant sur la page recevront la réponse et enverront à nouveau les requêtes Ajax, en répétant le processus ci-dessus.
<%@ 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>
Nous avons remarqué que la demande envoyée par btn n'a pas réellement besoin de réponse. La clé de tout le processus est que le client garde toujours le serveur connecté () à la demande. Le côté serveur doit d'abord prendre en charge cette méthode de réponse asynchrone. Heureusement, la plupart des conteneurs de servlets ont jusqu'à présent fourni un bon support. Prenons Tomcat comme exemple ci-dessous :
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 est une implémentation thread-safe de la file d'attente Queue, qui est utilisée ici comme conteneur pour enregistrer les requêtes. AsyncContext est un environnement asynchrone pris en charge par Tomcat et différents serveurs utilisent des objets légèrement différents. L'objet pris en charge par Jetty est Continuation. La requête qui a terminé la diffusion doit mettre fin à la requête associée via context.complete() et utiliser CONNECTIONS.remove(context) pour supprimer la file d'attente.
2. WebSocket (prise en charge de HTML5)
Comet utilisant l'interrogation longue HTTP est le meilleur moyen d'implémenter de manière fiable la méthode Ajax inversée, car tout les navigateurs prennent désormais en charge cela.
Les WebSockets sont apparus en HTML5 et sont une technologie Ajax inversée plus récente que Comet. Les WebSockets prennent en charge un canal de communication bidirectionnel en duplex intégral, et de nombreux navigateurs (Firefox, Google Chrome et Safari) le prennent également en charge. Les connexions sont établies via des requêtes HTTP (également appelées poignées de main WebSockets) et certains en-têtes spéciaux. La connexion est toujours active et vous pouvez écrire et recevoir des données en JavaScript comme vous le feriez avec un socket TCP brut.
Démarrez l'URL WebSocket en saisissant ws:// ou wss:// (sur SSL). Comme le montre l'image :
Tout d'abord : les WebSockets ne sont pas bien pris en charge sur tous les navigateurs, et évidemment IE se retient. Par conséquent, lorsque vous envisagez d'utiliser cette technologie, vous devez tenir compte de l'environnement d'utilisation de l'utilisateur. Si votre projet concerne Internet ou inclut des utilisateurs de téléphones mobiles, je conseille à chacun d'y réfléchir à deux fois.
Deuxièmement : la requête fournie par WebSockets est différente de la requête HTTP ordinaire. Il s'agit d'une communication full-duplex et est toujours active (si vous ne la désactivez pas). Cela signifie que vous n'avez pas besoin d'envoyer à nouveau une requête au serveur à chaque fois que vous recevez une réponse, ce qui peut économiser beaucoup de ressources.
<%@ 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 n'a pas encore fourni un meilleur support pour WebSocket, il faut donc utiliser Javascript pour écrire une partie du code (heureusement ce n'est pas compliqué). Et certains serveurs courants peuvent prendre en charge les requêtes ws, en prenant Tomcat comme exemple. Dans la version 6.0, l'objet WebSocketServlet a été marqué comme @java.lang.Deprecated. Les versions ultérieures à 7.0 prennent en charge l'implémentation fournie par jsr365, vous devez donc utiliser des annotations pour effectuer les configurations pertinentes.
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.Résumé (de la demande au push)
Dans un schéma de communication traditionnel, si le système A a besoin d'informations du système B, il enverra une requête au système B. Le système B traitera la demande pendant que le système A attend la réponse. Une fois le traitement terminé, la réponse est renvoyée au système A. En mode de communication synchrone, l'utilisation des ressources est moins efficace car le temps de traitement est perdu à attendre une réponse.
En mode asynchrone, le système A s'abonnera aux informations qu'il souhaite obtenir du système B. Le système A peut alors envoyer une notification au système B, ou les informations peuvent être renvoyées immédiatement, tandis que le système A peut gérer d'autres transactions. Cette étape est facultative. Dans une application basée sur les événements, vous n'avez généralement pas besoin de demander à d'autres systèmes d'envoyer des événements, car vous ne savez pas de quoi il s'agit. Le système A reçoit la réponse immédiatement après que le système B l'a publiée.
Les frameworks Web s'appuyaient autrefois sur le modèle traditionnel « requête-réponse », ce qui entraînait une actualisation de la page. Avec l'avènement d'Ajax, Reverse Ajax et WebSocket, il est désormais possible d'appliquer facilement les concepts d'architecture événementielle au Web, bénéficiant ainsi des avantages du découplage, de l'évolutivité et de la réactivité. Une meilleure expérience utilisateur apportera également de nouvelles opportunités commerciales.
J'ai compilé ce qui précède pour vous, j'espère que cela vous sera utile à l'avenir.
Articles connexes :
Ajax implémente la fonction de recherche d'invite intelligente
Ouvrir une nouvelle adresse de fenêtre une fois la requête Ajax réussie
Utiliser ajax pour implémenter des demandes d'actualisation asynchrones
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!