国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java后端WebSocket的Tomcat實現

2019-11-15 01:15:51
字體:
來源:轉載
供稿:網友
java后端WebSocket的Tomcat實現

隨著互聯網的發展,傳統的HTTP協議已經很難滿足Web應用日益復雜的需求了。近年來,隨著HTML5的誕生,WebSocket協議被提出,它實現了瀏覽器與服務器的全雙工通信,擴展了瀏覽器與服務端的通信功能,使服務端也能主動向客戶端發送數據。

我們知道,傳統的HTTP協議是無狀態的,每次請求(request)都要由客戶端(如瀏覽器)主動發起,服務端進行處理后返回response結果,而服務端很難主動向客戶端發送數據;這種客戶端是主動方,服務端是被動方的傳統Web模式對于信息變化不頻繁的Web應用來說造成的麻煩較小,而對于涉及實時信息的Web應用卻帶來了很大的不便,如帶有即時通信、實時數據、訂閱推送等功能的應用。在WebSocket規范提出之前,開發人員若要實現這些實時性較強的功能,經常會使用折衷的解決方法:輪詢(polling)和Comet技術。其實后者本質上也是一種輪詢,只不過有所改進。

輪詢是最原始的實現實時Web應用的解決方案。輪詢技術要求客戶端以設定的時間間隔周期性地向服務端發送請求,頻繁地查詢是否有新的數據改動。明顯地,這種方法會導致過多不必要的請求,浪費流量和服務器資源。

Comet技術又可以分為長輪詢和流技術。長輪詢改進了上述的輪詢技術,減小了無用的請求。它會為某些數據設定過期時間,當數據過期后才會向服務端發送請求;這種機制適合數據的改動不是特別頻繁的情況。流技術通常是指客戶端使用一個隱藏的窗口與服務端建立一個HTTP長連接,服務端會不斷更新連接狀態以保持HTTP長連接存活;這樣的話,服務端就可以通過這條長連接主動將數據發送給客戶端;流技術在大并發環境下,可能會考驗到服務端的性能。

這兩種技術都是基于請求-應答模式,都不算是真正意義上的實時技術;它們的每一次請求、應答,都浪費了一定流量在相同的頭部信息上,并且開發復雜度也較大。

伴隨著HTML5推出的WebSocket,真正實現了Web的實時通信,使B/S模式具備了C/S模式的實時通信能力。WebSocket的工作流程是這樣的:瀏覽器通過JavaScript向服務端發出建立WebSocket連接的請求,在WebSocket連接建立成功后,客戶端和服務端就可以通過TCP連接傳輸數據。因為WebSocket連接本質上是TCP連接,不需要每次傳輸都帶上重復的頭部數據,所以它的數據傳輸量比輪詢和Comet技術小了很多。本文不詳細地介紹WebSocket規范,主要介紹下WebSocket在Java Web中的實現。

JavaEE 7中出了JSR-356:Java API for WebSocket規范。不少Web容器,如Tomcat,Nginx,Jetty等都支持WebSocket。Tomcat從7.0.27開始支持WebSocket,從7.0.47開始支持JSR-356,下面的Demo代碼也是需要部署在Tomcat7.0.47上才能運行。

對瀏覽器的支持情況:

新建一個dynamic web項目:

客戶端(Web主頁)代碼:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%><%Stringpath=request.getContextPath();StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPEHTML><html><head><basehref="<%=basePath%>"><title>MyWebSocket</title></head><body>Welcome<br/><inputid="text"type="text"/><buttononclick="send()">Send</button><buttononclick="closeWebSocket()">Close</button><divid="message"></div></body><scripttype="text/Javascript">varwebsocket=null;//判斷當前瀏覽器是否支持WebSocketif('WebSocket'inwindow){websocket=newWebSocket("ws://localhost:8080/MyWebSocket/websocket");}else{alert('Notsupportwebsocket')}//連接發生錯誤的回調方法websocket.onerror=function(){setMessageInnerHTML("error");};//連接成功建立的回調方法websocket.onopen=function(event){setMessageInnerHTML("open");}//接收到消息的回調方法websocket.onmessage=function(){setMessageInnerHTML(event.data);}//連接關閉的回調方法websocket.onclose=function(){setMessageInnerHTML("close");}//監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。window.onbeforeunload=function(){websocket.close();}//將消息顯示在網頁上functionsetMessageInnerHTML(innerHTML){document.getElementById('message').innerHTML+=innerHTML+'<br/>';}//關閉連接functioncloseWebSocket(){websocket.close();}//發送消息functionsend(){varmessage=document.getElementById('text').value;websocket.send(message);}</script></html>

Java Web后端代碼

創建一個注解為:@ServerEndpoint的webscoket的服務端.供前臺訪問.因為想實現點其它功能.所以在廣播給所有人這個方法里邊加上了type以備區分

注解說明圖:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798packagecom.chen.websocket;importjava.io.IOException;importjava.util.concurrent.CopyOnWriteArraySet;importjavax.websocket.OnClose;importjavax.websocket.OnError;importjavax.websocket.OnMessage;importjavax.websocket.OnOpen;importjavax.websocket.session;importjavax.websocket.server.ServerEndpoint;//該注解用來指定一個URI,客戶端可以通過這個URI來連接到WebSocket。類似Servlet的注解mapping。無需在web.xml中配置。@ServerEndpoint("/websocket")publicclassMyWebSocket{//靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。PRivatestaticintonlineCount=0;//concurrent包的線程安全Set,用來存放每個客戶端對應的MyWebSocket對象。若要實現服務端與單一客戶端通信的話,可以使用Map來存放,其中Key可以為用戶標識privatestaticCopyOnWriteArraySet<MyWebSocket>webSocketSet=newCopyOnWriteArraySet<MyWebSocket>();//與某個客戶端的連接會話,需要通過它來給客戶端發送數據privateSessionsession;/***連接建立成功調用的方法*@paramsession可選的參數。session為與某個客戶端的連接會話,需要通過它來給客戶端發送數據*/@OnOpenpublicvoidonOpen(Sessionsession){this.session=session;webSocketSet.add(this);//加入set中addOnlineCount();//在線數加1System.out.println("有新連接加入!當前在線人數為"+getOnlineCount());}/***連接關閉調用的方法*/@OnClosepublicvoidonClose(){webSocketSet.remove(this);//從set中刪除subOnlineCount();//在線數減1System.out.println("有一連接關閉!當前在線人數為"+getOnlineCount());}/***收到客戶端消息后調用的方法*@parammessage客戶端發送過來的消息*@paramsession可選的參數*/@OnMessagepublicvoidonMessage(Stringmessage,Sessionsession){System.out.println("來自客戶端的消息:"+message);//群發消息for(MyWebSocketitem:webSocketSet){try{item.sendMessage(message);}catch(IOExceptione){e.printStackTrace();continue;}}}/***發生錯誤時調用*@paramsession*@paramerror*/@OnErrorpublicvoidonError(Sessionsession,Throwableerror){System.out.println("發生錯誤");error.printStackTrace();}/***這個方法與上面幾個方法不一樣。沒有用注解,是根據自己需要添加的方法。*@parammessage*@throwsIOException*/publicvoidsendMessage(Stringmessage)throwsIOException{this.session.getBasicRemote().sendText(message);//this.session.getAsyncRemote().sendText(message);}publicstaticsynchronizedintgetOnlineCount(){returnonlineCount;}publicstaticsynchronizedvoidaddOnlineCount(){MyWebSocket.onlineCount++;}publicstaticsynchronizedvoidsubOnlineCount(){MyWebSocket.onlineCount--;}}

該Demo在以下環境測試過:

1.Jdk7+Tomcat7.0.47

2.Jdk7+Tomcat7.0.52

3.Jdk7+Tomcat8.0.3

4.Jdk7+Glassfish4

注意事項:在Eclipse或者MyEclipse中,需要添加Tomcat的library。直接拷貝Tomcat里lib目錄下的jar包有時會出錯。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 石台县| 治县。| 阳城县| 皋兰县| 宝清县| 轮台县| 申扎县| 敦化市| 阿合奇县| 泾源县| 北票市| 缙云县| 石棉县| 成武县| 龙海市| 南汇区| 苏尼特左旗| 葫芦岛市| 漠河县| 香格里拉县| 板桥市| 微山县| 峡江县| 尼勒克县| 光山县| 高尔夫| 原平市| 合山市| 视频| 炎陵县| 额尔古纳市| 合作市| 巨鹿县| 绥芬河市| 宁海县| 襄汾县| 新宁县| 梓潼县| 无锡市| 唐河县| 丰宁|