Servlet3异步特性+Ajax+Websocket

 Java Servlet 3.0有了异步特性,这使得服务器端可以推后处理某些请求。 Ajax可以使得客户端post部分请求,并接受异步回调。 websocket可以使得客户端与服务器进行全双工的通讯,客户端接受ServerPush信息很容易。  1. use servlet3.0 async feature   1.1 服务器端代码(异步Servlet) servletpath:/AsyncPath - in server side @WebServlet(urlPatterns={"/AsyncPath"},asyncSupported=true) public class AsyncServlet extends HttpServlet   1.2. access the async url on web browser chrome - in client side (在浏览器输�%Fspan> result.add(ServerEndpointConfig.Builder.create(EchoEndpoint.class,  "/websocket/echoProgrammatic").build());  }    if (scanned.contains(EchoEndpoint.class)) {  result.add(ServerEndpointConfig.Builder.create(EchoEndpointAsync.class,  "/websocket/echoProgrammaticAsync").build());  }   return result;  }   @Override  public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {  // Deploy all WebSocket endpoints defined by annotations in the examples  // web application. Filter out all others to avoid issues when running  // tests on Gump  Set<Class<?>> results = new HashSet<Class<?>>();  for (Class<?> clazz : scanned) {  if (clazz.getPackage().getName().startsWith("websocket.")) {  results.add(clazz);  }  }  return results;  } }  2.2 EchoEndpointAsync  package websocket.echo; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.websocket.Endpoint; import javax.websocket.EndpointConfig; import javax.websocket.MessageHandler; import javax.websocket.Rem5�http://localhost:8080/SMPUI/AsyncPath?name=tony&age=42&delay=4,然后敲回车) Async servlet starts:Mon Feb 29 14:20:01 CST 2016 </br> OK </br> Async servlet ends :Mon Feb 29 14:20:01 CST 2016 </br> </br> Event 1 started...Mon Feb 29 14:20:01 CST 2016</br> Event 2 started...Mon Feb 29 14:20:06 CST 2016</br> Event 3 started...Mon Feb 29 14:20:06 CST 2016</br>  浏览器的忙碌图标还是至少5秒以上。   2. use servlet traditional feature (sync) in server side   2.1 服务器端代码(同步Servlet) servletpath:/SyncPath -in server side @WebServlet("/SyncPath")  2.2 access the async url on web browser chrome - in client side (在浏览器输入http://localhost:8080/SMPUI/AsyncPath?name=tony&age=42&delay=4,然后敲回车) Sync servlet starts:Mon Feb 29 16:38:23 CST 2016 </br> Event 1 started...Mon Feb 29 16:38:23 CST 2016</br> Event 2 started...Mon Feb 29 16:38:27 CST 2016</br> Event 3 started...Mon Feb 29 16:38:27 CST 2016</br> OK </br> Sync servlet ends :Mon Feb 29 16:38:27 CST 2016 </br> </br>  浏览器的忙碌图标还是至少5秒以上。  由1,2可总结: 这种异步带来的好处是在服务器端的,对客户端纯浏览器(无Ajax)操作并无改善。 异步的好处是:服务器异步工作。可以先缓存大量请求,然后业务逻辑的处理可以延迟进行。 缺点是:客户端仍是阻塞式等待。  在同步环境下,service(HttpServletRequest request, HttpServletResponse response) 执行完成(出了这个方法)后,其request, response 不能再使用。 在异步环境下,service(HttpServletRequest request, HttpServletResponse response) 执行完成后,在另外的线程中仍可以使用asyncontext得到response来向客户端写。这就是本质区别。  3. Use Ajax in client (Web browser)  (在浏览器输入http://localhost:8080/SMPUI/AsyncPath回车后,点击Submit按钮)  var xhttp = new XMLHttpRequest();  var url="http://localhost:8080/SMPUI/AsyncPath";  xhttp.open("GET", url, true); //true = ajax  xhttp.send();    点击Submit按钮后看到的结果:  Async servlet starts:Tue Mar 01 17:00:27 CST 2016   OK   Async servlet ends :Tue Mar 01 17:00:27 CST 2016    Event 1 started...Tue Mar 01 17:00:27 CST 2016  Event 2 started...Tue Mar 01 17:00:37 CST 2016  Event 3 started...Tue Mar 01 17:00:37 CST 2016   浏览器图标不再忙碌    由3总结:  浏览器异步发送方和接收结果,导致浏览器忙碌图标不再是不停转动10秒后再显示,而是很平静的过一会(10秒)把服务器延迟产生的数据也显示出来。  服务器端仍然是异步工作。  好处是:客户端不再阻塞式等待结果,而是利用回调函数处理服务器发来的数据。    缺点是:还是靠拉的方式。 不是服务器主动推的方式。[客户端主动发一次请求服务器才有响应,客户端不发请求服务器没有响应,客户端发几次请求服务器有几次响应]  即使客户端做成轮询的方式[每隔几秒发一次请求],运行若干(10-20)分钟后浏览器页面会崩溃,显然不是可接受的方式。   4. Use WebSocket 实现全双工通信。每次客户端发的请求都有回应,同时客户端还可以接受服务器推的信息。 1.客户端:echoAsync.xhtml  <?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head>  <title>Tomcat WebSocket Async Examples: Echo</title>  <style type="text/css"><![CDATA[  #connect-container {  float: left;  width: 400px  }   #connect-container div {  padding: 5px;  }   #console-container {  float: left;  margin-left: 15px;  width: 400px;  }   #console {  border: 1px solid #CCCCCC;  border-right-color: #999999;  border-bottom-color: #999999;  height: 170px;  overflow-y: scroll;  padding: 5px;  width: 100%;  }   #console p {  padding: 0;  margin: 0;  }  ]]></style>  <script type="application/javascript"><![CDATA[  var ws = null;   function setConnected(connected) {  document.getElementById('connect').disabled = connected;  document.getElementById('disconnect').disabled = !connected;  document.getElementById('echo').disabled = !connected;  }   function connect() {  var target = document.getElementById('target').value;  if (target == '') {  alert('Please select server side connection implementation.');  return;  }  if ('WebSocket' in window) {  ws = new WebSocket(target);  } else if ('MozWebSocket' in window) {  ws = new MozWebSocket(target);  } else {  alert('WebSocket is not supported by this browser.');  return;  }  ws.onopen = function () {  setConnected(true);  log('Info: WebSocket connection opened.');  };  ws.onmessage = function (event) {  log('Received: ' + event.data);  };  ws.onclose = function (event) {  setConnected(false);  log('Info: WebSocket connection closed, Code: ' + event.code + (event.reason == "" ? "" : ", Reason: " + event.reason));  };  }   function disconnect() {  if (ws != null) {  ws.close();  ws = null;  }  setConnected(false);  }   function echo() {  if (ws != null) {  var message = document.getElementById('message').value;  log('Sent: ' + message);  ws.send(message);  } else {  alert('WebSocket connection not established, please connect.');  oteEndpoint;         }          function updateTarget(target) {             if (window.location.protocol == 'http:') {                 document.getElementById('target').value = 'ws://' + window.location.host + target;             } else {                 document.getElementById('target').value = 'wss://' + window.location.host + target;             }         }          function log(message) {             var console = document.getElementById('console');             var p = document.createElement('p');             p.style.wordWrap = 'break-word';             p.appendChild(document.createTextNode(message));             console.appendChild(p);             while (console.childNodes.length > 25) {                 console.removeChild(console.firstChild);             }             console.scrollTop = console.scrollHeight;         }           document.addEventListener("DOMContentLoaded", function() {             // Remove elements with "noscript" class - <noscript> is not allowed in XHTML             var noscripts = document.getElementsByClassName("noscript");             for (var i = 0; i < noscripts.length; i++) {                 noscripts[i].parentNode.removeChild(noscripts[i]);             }         }, false);     ]]></script> </head>
<body>
<div class="noscript"><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
    Javascript and reload this page!</h2></div>
<div>
    <div id="connect-container">
        <div>
            <span>Connect to service implemented using:</span>
            <!-- echo example using new programmatic API on the server side -->
            <input id="radio1" type="radio" name="group1" value="/SMPUI/websocket/echoProgrammaticAsync"
                   onclick="updateTarget(this.value);"/> <label for="radio1">programmatic API</label>
            <!-- echo example using new annotation API on the server side -->
            <input id="radio2" type="radio" name="group1" value="/SMPUI/websocket/echoAnnotation"
                   onclick="updateTarget(this.value);"/> <label for="radio2">annotation API</label>
        </div>
        <div>
            <input id="target" type="text" size="40" style="width: 350px"/>
        </div>
        <div>
            <button id="connect" onclick="connect();">Connect</button>
            <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
        </div>
        <div>
            <textarea id="message" style="width: 350px">Here is a message!</textarea>
        </div>
        <div>
            <button id="echo" onclick="echo();" disabled="disabled">Echo message</button>
        </div>
    </div>
    <div id="console-container">
        <div id="console"/>
    </div>
</div>
</body>
</html>



2.服务器端:
2.1 ExamplesConfig
package websocket;

import java.util.HashSet;
import java.util.Set;

import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
import websocket.echo.EchoEndpoint;
import websocket.echo.EchoEndpointAsync;

public class ExamplesConfig implements ServerApplicationConfig {

	@Override 	public Set<ServerEndpointConfig> getEndpointConfigs( Set<Class<? extends Endpoint>> scanned) {  		Set<ServerEndpointConfig> result = new HashSet<ServerEndpointConfig>();  		if (scanned.contains(EchoEndpoint.class)) { 

你可能感兴趣的:(Servlet3异步特性+Ajax+Websocket)