function ajax(data){ var xhr = new XMLHttpRequest(); xhr.open('get', '/cgi-bin/xxx', true); xhr.onreadystatechange = function(){ if (xhr.readyState == 4) { if (xhr.status == 200) { ...... } } } xhr.send(data); } setTimeout(function(){ajax({"data":"hehe"});}, 2000);//每隔2秒請求一次
function ajax(data){
var xhr = new XMLHttpRequest();
xhr.open('get', '/cgi-bin/xxx', true);
xhr.onreadystatechange = function(){
if (xhr.readyState == 4) {
if (xhr.status == 200) {
}
}
}
xhr.send(data);
}
setTimeout(function(){ajax({"data":"hehe"});}, 2000);//每隔2秒請求一次
Ajax
輪詢與基於Ajax
的長輪詢原理對比: 圖4-2
function longPoll(data, cbk){ var xhr = new XMLHttpRequest(); var url = '/cgi-bin/xxx'; xhr.onreadystatechange = function(){ if (xhr.readyState == 4) {//XMLHttpRequest 的狀態中4: 請求已完成,且響應已就緒 if (xhr.status == 200) { //請求完畢後從新發起新的一次鏈接 cbk(xhr.responseText); xhr.open('get', url, true); xhr.send(otherData); } } } xhr.open('get', url, true); xhr.send(data); }
x
function longPoll(data, cbk){
var xhr = new XMLHttpRequest();
var url = '/cgi-bin/xxx';
xhr.onreadystatechange = function(){
if (xhr.readyState == 4) {//XMLHttpRequest 的狀態中4: 請求已完成,且響應已就緒
if (xhr.status == 200) { //請求完畢後從新發起新的一次鏈接
cbk(xhr.responseText);
xhr.open('get', url, true);
xhr.send(otherData);
}
}
}
xhr.open('get', url, true);
xhr.send(data);
}
web.xml
中application的配置的版本是3.0
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <filter> <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> <filter-class>org.springframework.~.OpenEntityManagerInViewFilter</filter-class> <async-supported>true</async-supported> </filter> <filter-mapping> <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>ASYNC</dispatcher> </filter-mapping> </web-app>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<filter>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.~.OpenEntityManagerInViewFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ASYNC</dispatcher>
</filter-mapping>
</web-app>
WebApplicationInitializer
,你一樣須要像在
web.xml
中同樣,設置」asyncSupported」標籤爲ASYNC.爲了簡化這個配置,考慮繼承
AbstractDispatcherServletInitializer
或者
AbstractAnnotationConfigDispatcherServletInitializer
。它們會自動設置這些選項,使它很容易註冊過濾器實例。
asyncContext.addListener(new AsyncListener() { //這裏爲異步處理提供了一個監聽器,使用AsyncListener接口表示。此接口負責管理異步事件 @Override public void onComplete(AsyncEvent event) throws IOException { } //超時處理,注意asyncContext.complete();,表示請求處理完成 @Override public void onTimeout(AsyncEvent event) throws IOException { AsyncContext asyncContext = event.getAsyncContext(); asyncContext.complete(); } @Override public void onError(AsyncEvent event) throws IOException { } @Override public void onStartAsync(AsyncEvent event) throws IOException { } });
asyncContext.addListener(new AsyncListener() { //這裏爲異步處理提供了一個監聽器,使用AsyncListener接口表示。此接口負責管理異步事件
@Override
public void onComplete(AsyncEvent event) throws IOException {
}
//超時處理,注意asyncContext.complete();,表示請求處理完成
@Override
public void onTimeout(AsyncEvent event) throws IOException {
AsyncContext asyncContext = event.getAsyncContext();
asyncContext.complete();
}
@Override
public void onError(AsyncEvent event) throws IOException {
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
}
});
DeferredResult
的處理順序與Callable十分類似,由應用程序多線程產生異步結果:javascript
DeferredResult
對象,而且把它保存在內在隊列當中或者能夠訪問它的列表中。DispatcherServlet
與全部的Filter的Servlet容器線程退出,但Response仍然開放。DeferredResult
中sets值.而且Spring MVC分發request給Servlet容器.DispatcherServlet
再次被調用而且繼續異步的處理產生的結果.Spring MVC提供Java Config與MVC namespace做爲選擇用來配置處理異步request.WebMvcConfigurer能夠經過configureAsyncSupport來進行配置,而xml能夠經過子元素來進行配置.html
若是你不想依賴Servlet容器(e.g. Tomcat是10)配置的值,容許你配置異步請求默認的timeout值。你能夠配置AsyncTaskExecutor
用來包含Callable
實例做爲controller方法的返回值.強烈建議配置這個屬性,由於在默認狀況下Spring MVC使用SimpleAsyncTaskExecutor
。Spring MVC中Java配置與namespace容許你註冊CallableProcessingInterceptor
與DeferredResultProcessingInterceptor
實例.前端
若是你想覆蓋DeferredResult
的默認過時時間,你能夠選擇使用合適的構造器.一樣的,對於Callable
,你能夠經過WebAsyncTask
來包裝它而且使用相應的構造器來定製化過時時間.WebAsyncTask
的構造器一樣容許你提供一個AsyncTaskExecutor
.html5
原文地址:spring-framework-reference-4.2.6.RELEASEjava
function foreverFrame(url,callback){ var iframe = body.appendChild(document.createElement("iframe")); iframe.style.display="none"; iframe.src=url+"?callback=parent.foreverFrame.callback"; this.callback = callback; }
function foreverFrame(url,callback){
var iframe = body.appendChild(document.createElement("iframe"));
iframe.style.display="none";
iframe.src=url+"?callback=parent.foreverFrame.callback";
this.callback = callback;
}
<script> parent.foreverFrame.callback('hello world!'); </script> <script> parent.foreverFrame.callback('hello Mars!'); </script>
<script>
parent.foreverFrame.callback('hello world!');
</script>
<script>
parent.foreverFrame.callback('hello Mars!');
</script>
function xhrStreaming(url, callback) { var xhr = new XMLHttpRequest(); xhr.open('post', url, true); //保存上次返回的文檔位置 var lastSize; xhr.onreadystatechange = function() { var newResponseText = ""; if (xhr.readyState > 2) { newResponseText = xhr.responseText.slice(lastSize); lastSize = xhr.responseText.length; callback(newResponseText); } if (xhr.readyState == 4) { xhrStreaming(url, callback); } } xhr.send(null); }
function xhrStreaming(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('post', url, true);
//保存上次返回的文檔位置
var lastSize;
xhr.onreadystatechange = function() {
var newResponseText = "";
if (xhr.readyState > 2) {
newResponseText = xhr.responseText.slice(lastSize);
lastSize = xhr.responseText.length;
callback(newResponseText);
}
if (xhr.readyState == 4) {
xhrStreaming(url, callback);
}
}
xhr.send(null);
}
protocol="org.apache.coyote.http11.Http11NioProtocol"
protocol="org.apache.coyote.http11.Http11NioProtocol"
var supported = ("WebSocket" in window); if (supported) alert("WebSockets are supported");
var supported = ("WebSocket" in window);
if (supported) alert("WebSockets are supported");
var connection = new WebSocket('ws://localhost:8080'); // When the connection is open, send some data to the server connection.onopen = function () { connection.send('Ping'); // Send the message 'Ping' to the server }; // Log errors connection.onerror = function (error) { console.log('WebSocket Error ' + error); }; // Log messages from the server connection.onmessage = function (e) { console.log('Server: ' + e.data); };
var connection = new WebSocket('ws://localhost:8080');
// When the connection is open, send some data to the server connection.onopen = function () { connection.send('Ping'); // Send the message 'Ping' to the server }; // Log errors connection.onerror = function (error) { console.log('WebSocket Error ' + error); }; // Log messages from the server connection.onmessage = function (e) { console.log('Server: ' + e.data); };
Connection:Upgrade Sec-WebSocket-Key:eDCPPyPQZq7PiwRcx8SPog== Sec-WebSocket-Version:13 Upgrade:websocket
Connection:Upgrade Sec-WebSocket-Key:eDCPPyPQZq7PiwRcx8SPog== Sec-WebSocket-Version:13 Upgrade:websocket
HTTP/1.1 101 Switching Protocols Upgrade:websocket Connection:upgrade Sec-WebSocket-Accept:QJsTRym36zHnArQ7FCmSdPhuK78= // Connection:upgrade 升級被服務器贊成 // Upgrade:websocket 指示客戶端升級到websocket // Sec-WebSocket-Accept:參考上面請求的Sec-WebSocket-Key的註釋
HTTP/1.1 101 Switching Protocols
Upgrade:websocket
Connection:upgrade
Sec-WebSocket-Accept:QJsTRym36zHnArQ7FCmSdPhuK78=
// Connection:upgrade 升級被服務器贊成
// Upgrade:websocket 指示客戶端升級到websocket
// Sec-WebSocket-Accept:參考上面請求的Sec-WebSocket-Key的註釋
TIP
代理、不少現有的HTTP
中間設備可能不理解新的WebSocket
協議,而這可能致使各類問題,使用時須要注意,可使藉助TLS
,經過創建一條端到端的加密信道,可讓WebSocket
通訊繞過全部中間代理。