一、 WebSocket介紹:
WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協議。
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。
在 WebSocket API 中,瀏覽器和服務器只需要做一個握手的動作,然後,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。
現在,很多網站爲了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的帶寬等資源。
HTML5 定義的 WebSocket 協議,能更好的節省服務器資源和帶寬,並且能夠更實時地進行通訊。
二、傳統的Ajax 輪詢代碼
下面是script中寫的Ajax輪詢方法
Ajax方法寫好後,要調用Window setInterval() 這個方法,數值以毫秒計算。
function getEvents(){
$.ajax({
async: false,
type: "get",
url: url,
dataType: "json",
success(data) {
//返回後的數據處理。
)
}
}
})
}
getEvents(); //頁面加載便執行方法
setInterval(function(){
getEvents();
},15000); //每15秒執行一次。
三、 WebSocket持續推送。
頁面代碼:
<input id="text" type="text"/>
<button onclick="send()">發送消息</button>
<hr/>
<button onclick="closeWebSocket()">關閉WebSocket連接</button>
<hr/>
<div id="message"></div>
<script>代碼:
var websocket = null;
//判斷當前瀏覽器是否支持WebSocket
if('WebSocket' in window){
//連接WebSocket節點訪問後臺的URL路徑,002是參數。
websocket = new WebSocket("ws://localhost:8080/admin/productWebSocket");
}
else{
alert('Not support websocket')
}
//連接發生錯誤的回調方法
websocket.onerror = function(){
setMessageInnerHTML("error");
};
//連接成功建立即執行的方法
websocket.onopen = function(event){
setMessageInnerHTML("open");//調用下面的方法。
}
//接收到消息的回調方法
websocket.onmessage = function(event){
setMessageInnerHTML(event.data);
//對數據進行處理。
}
//連接關閉的回調方法
websocket.onclose = function(){
setMessageInnerHTML("close");
}
//監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。
window.onbeforeunload = function(){
websocket.close();
}
//將消息顯示在網頁上
function setMessageInnerHTML(innerHTML){
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
//發送消息
function send(){
var message = document.getElementById('text').value;
websocket.send(message);
}
//關閉連接
function closeWebSocket(){
websocket.close();
}
後臺 WebSocket代碼:
@Component
@ServerEndpoint(value = "/admin/productWebSocket", configurator = MyEndpointConfigure.class)
public class ProductWebSocket {
// 靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。
private static final AtomicInteger OnlineCount = new AtomicInteger(0);
// concurrent包的線程安全Set,用來存放每個客戶端對應的ProductWebSocket對象。
private static CopyOnWriteArraySet<ProductWebSocket> webSocketSet = new CopyOnWriteArraySet<ProductWebSocket>();
// 與某個客戶端的連接會話,需要通過它來給客戶端發送數據
private Session session;
private Logger log = LoggerFactory.getLogger(ProductWebSocket.class);
/**
* 連接建立成功調用的方法
*/
@OnOpen
public void onOpen(@PathParam("userId")String titleId, Session session) {
log.info("新客戶端連入,用戶id:" + titleId);//titleId 便是後面跟的002參數
ProductWebSocket client = new ProductWebSocket();
client.session = session;
client.webSocketSet = webSocketSet;
client.carId=titleId;
if("002".equals(titleId)) {
webSocketSet.add(client); // 加入set中
}
System.out.println("-當前在線人數爲:"+getOnlineCount());
}
/**
* 連接關閉調用的方法
*/
@OnClose
public void onClose(Session session) {
log.info("一個客戶端關閉連接");
for (ProductWebSocket productWebSocket : webSocketSet) {
if (productWebSocket.session.equals(session)) {
webSocketSet.remove(productWebSocket);
}
}
}
/**
* 收到客戶端消息後調用的方法
*
* @param message
* 客戶端發送過來的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("用戶發送過來的消息爲:"+message);
//羣發消息
for(ProductWebSocket item: webSocketSet){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
/**
* 發生錯誤時調用
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("websocket出現錯誤");
error.printStackTrace();
}
public void sendMessage(String message) {
try {
this.session.getBasicRemote().sendText(message);
log.info("推送消息成功,消息爲:" + message);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 羣發自定義消息
*/
public static void sendInfo(String message) throws IOException {
for (ProductWebSocket productWebSocket : webSocketSet) {
productWebSocket.sendMessage(message);
}
}
public static synchronized int getOnlineCount() {
return OnlineCount.get();
}
public static synchronized void addOnlineCount() {
OnlineCount.incrementAndGet(); // 在線數加1
}
public static synchronized void subOnlineCount() {
OnlineCount.decrementAndGet(); // 在線數加1
}
}
以上便是使用WebSocket的一點經驗,代碼多變,方法也不盡相同。僅留作日後參考。
有錯誤還請大家指正。