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-2function 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十分相似,由应用程序多线程产生异步结果:
DeferredResult
对象,并且把它保存在内在队列当中或者可以访问它的列表中。DispatcherServlet
与所有的Filter的Servlet容器线程退出,但Response仍然开放。DeferredResult
中sets值.并且Spring MVC分发request给Servlet容器.DispatcherServlet
再次被调用并且继续异步的处理产生的结果.Spring MVC提供Java Config与MVC namespace作为选择用来配置处理异步request.WebMvcConfigurer可以通过configureAsyncSupport来进行配置,而xml可以通过子元素来进行配置.
如果你不想依赖Servlet容器(e.g. Tomcat是10)配置的值,允许你配置异步请求默认的timeout值。你可以配置AsyncTaskExecutor
用来包含Callable
实例作为controller方法的返回值.强烈建议配置这个属性,因为在默认情况下Spring MVC使用SimpleAsyncTaskExecutor
。Spring MVC中Java配置与namespace允许你注册CallableProcessingInterceptor
与DeferredResultProcessingInterceptor
实例.
如果你想覆盖DeferredResult
的默认过期时间,你可以选择使用合适的构造器.同样的,对于Callable
,你可以通过WebAsyncTask
来包装它并且使用相应的构造器来定制化过期时间.WebAsyncTask
的构造器同样允许你提供一个AsyncTaskExecutor
.
原文地址:spring-framework-reference-4.2.6.RELEASE
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
通信绕过所有中间代理。原文:https://www.cnblogs.com/redcoatjk/p/10846100.html