Home > Article > Web Front-end > Master reverse Ajax in 30 minutes
This article mainly introduces the relevant information about reverse Ajax that can be mastered quickly in 30 minutes. Friends who need it can refer to it
Scenario 1: When there is a new email, the web page automatically pops up a prompt message without the need for the user Manually refresh your inbox.
Scenario 2: After the user’s mobile phone scans the QR code on the page, the page will automatically jump.
Scenario 3: If anyone speaks in an environment similar to a chat room, all logged-in users can see the message immediately.
Compared with the traditional MVC model, where requests must be initiated from the client and responded to by the server, using reverse Ajax can simulate the server actively pushing events to the client to improve user experience. This article will discuss reverse Ajax technology in two parts, including: Comet and WebSocket. The article aims to demonstrate how to implement the above two technical means, and the application in Struts2 or SpringMVC is not covered. In addition, Servlet configuration also uses annotations. For relevant knowledge, you can refer to other materials.
1. Comet (the best compatibility method)
Comet is essentially a concept: being able to send messages from the server to The client sends data. In a standard HTTP Ajax request, data is sent to the server. Reverse Ajax simulates making an Ajax request in some specific way, so that the server can send events to the client as quickly as possible. Since ordinary HTTP requests are often accompanied by page jumps, and push events require the browser to stay on the same page or frame, the implementation of Comet can only be completed through Ajax.
Its implementation process is as follows: when the page is loaded, an Ajax request is sent to the server, and the server side obtains the request and saves it in a thread-safe container (usually for the queue). At the same time, the server can still respond to other requests normally. When the event that needs to be pushed arrives, the server traverses the requests in the container and deletes it after returning the response. Then all browsers staying on the page will get the response and send Ajax requests again, repeating the above process.
<%@ 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>
We noticed that the request sent by btn does not actually need to get a response. The key to the entire process is that the client always keeps the server connected() requesting. The server side first needs to support this asynchronous response method. Fortunately, most Servlet containers so far have provided good support. Take Tomcat as an example below:
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 is a thread-safe implementation of Queue queue, which is used here as a container to save requests. AsyncContext is an asynchronous environment supported by Tomcat, and different servers use slightly different objects. The object supported by Jetty is Continuation. The request that has completed the broadcast needs to end the related request through context.complete(), and use CONNECTIONS.remove(context) to delete the queue.
2. WebSocket (support from HTML5)
Comet using HTTP long polling is the best way to reliably implement reverse Ajax way, because all browsers now provide support for this.
WebSockets appeared in HTML5 and are a newer reverse Ajax technology than Comet. WebSockets support a two-way, full-duplex communication channel, and many browsers (Firefox, Google Chrome, and Safari) also support it. Connections are made through HTTP requests (also called WebSockets handshakes) and some special headers. The connection is always active and you can write and receive data in JavaScript just as you would with a raw TCP socket.
Start the WebSocket URL by entering ws:// or wss:// (on SSL). As shown in the picture:
First of all: WebSockets is not well supported on all browsers, and obviously IE is holding back. Therefore, when you plan to use this technology, you must consider the user's usage environment. If your project is for the Internet or includes mobile phone users, I advise everyone to think twice.
Secondly: The requests provided by WebSockets are different from ordinary HTTP requests. It is a full-duplex communication and is always active (if you do not turn it off). This means that you don't have to send a request to the server again every time you get a response, which can save a lot of resources.
<%@ 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 has not yet provided better support for WebSocket, so we must use Javascript to write part of the code (fortunately it is not complicated). And some common servers can support ws requests, taking Tomcat as an example. In version 6.0, the WebSocketServlet object has been marked as @java.lang.Deprecated. Versions after 7.0 support the implementation provided by jsr365, so you must use annotations to complete related configurations.
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. Summary (from request to push)
In a traditional communication scheme, if system A needs information from system B, it will send a request to system B. System B will handle the request while System A waits for the response. Once processing is complete, the response is sent back to System A. In synchronous communication mode, resource usage is less efficient because processing time is wasted waiting for a response.
In asynchronous mode, system A will subscribe to the information it wants to get from system B. System A can then send a notification to System B, or the information can be returned immediately, while System A can handle other transactions. This step is optional. In an event-driven application, you usually don't have to ask other systems to send events because you don't know what those events are. System A receives the response immediately after System B publishes it.
Web frameworks used to rely on the traditional "request-response" model, which resulted in a page refresh. With the advent of Ajax, Reverse Ajax, and WebSocket, it is now possible to easily apply the concepts of event-driven architecture to the Web, gaining the benefits of decoupling, scalability, and reactivity. A better user experience will also bring new business opportunities.
The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.
Related articles:
Ajax implements intelligent prompt search function
Open a new window address after the Ajax request is successful
Use ajax to implement asynchronous refresh request
The above is the detailed content of Master reverse Ajax in 30 minutes. For more information, please follow other related articles on the PHP Chinese website!