Servlet3异步特性+Ajax+Websocket

来源:互联网 发布:php工程师的工资 编辑:程序博客网 时间:2024/06/04 23:29
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;}@Overridepublic 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 GumpSet<Class<?>> results = new HashSet<Class<?>>();for (Class<?> clazz : scanned) {if (clazz.getPackage().getName().startsWith("websocket.")) {results.add(clazz);}}return results;}}2.2 EchoEndpointAsyncpackage 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 ExamplesConfigpackage 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 {@Overridepublic Set<ServerEndpointConfig> getEndpointConfigs( Set<Class<? extends Endpoint>> scanned) {Set<ServerEndpointConfig> result = new HashSet<ServerEndpointConfig>();if (scanned.contains(EchoEndpoint.class)) {
0 0
原创粉丝点击