中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

SpringBoot | 第十九章:web 應(yīng)用開發(fā)之 WebSocket

2018-09-17    來源:importnew

容器云強(qiáng)勢上線!快速搭建集群,上萬Linux鏡像隨意使用

前言

web開發(fā)也講解了三章了,這章節(jié)開始講解關(guān)于與前端通信相關(guān)知識。實(shí)現(xiàn)一個在線聊天室類似的功能或者后端推送消息到前端,在沒有WebSocket時,讀大學(xué)那伙還有接觸過DWR(Direct Web Remoting),也使用過輪詢的方式,當(dāng)Servlet3.0出來后,也有使用其異步連接機(jī)制進(jìn)行前后端通信的。今天我們就來說說WebSocket。它是HTML5開始提供的。

關(guān)于WebSocket

WebSocketHTML5開始提供的一種在單個TCP連接上進(jìn)行全雙工通訊的協(xié)議。

WebSocket API中,瀏覽器和服務(wù)器只需要做一個握手的動作,然后,瀏覽器和服務(wù)器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。

瀏覽器通過JavaScript向服務(wù)器發(fā)出建立WebSocket連接的請求,連接建立以后,客戶端和服務(wù)器端就可以通過TCP連接直接交換數(shù)據(jù)。

當(dāng)獲取Web Socket連接后,你可以通過?send()?方法來向服務(wù)器發(fā)送數(shù)據(jù),并通過?onmessage事件來接收服務(wù)器返回的數(shù)據(jù)。

對于前端,創(chuàng)建一個WebSocket對象,如下:

var Socket = new WebSocket(url, [protocol] );

說明:第一個參數(shù) url, 指定連接的 URL。第二個參數(shù) protocol 是可選的,指定了可接受的子協(xié)議。

WebSocker屬性

以下是WebSocket對象的屬性。假定我們使用了以上代碼創(chuàng)建了Socket對象:

屬性 描述
Socket.readyState 只讀屬性?readyState?表示連接狀態(tài),可以是以下值:
0 – 表示連接尚未建立。
1 – 表示連接已建立,可以進(jìn)行通信。
2 – 表示連接正在進(jìn)行關(guān)閉。
3 – 表示連接已經(jīng)關(guān)閉或者連接不能打開。
Socket.bufferedAmount 只讀屬性?bufferedAmount?已被 send() 放入正在隊(duì)列中等待傳輸,但是還沒有發(fā)出的 UTF-8 文本字節(jié)數(shù)。

WebSocket事件

以下是 WebSocket 對象的相關(guān)事件。假定我們使用了以上代碼創(chuàng)建了 Socket 對象:

事件 事件處理程序 描述
open Socket.onopen 連接建立時觸發(fā)
message Socket.onmessage 客戶端接收服務(wù)端數(shù)據(jù)時觸發(fā)
error Socket.onerror 通信發(fā)生錯誤時觸發(fā)
close Socket.onclose 連接關(guān)閉時觸發(fā)

WebSocket方法

以下是 WebSocket 對象的相關(guān)方法。假定我們使用了以上代碼創(chuàng)建了 Socket 對象:

方法 描述
Socket.send() 使用連接發(fā)送數(shù)據(jù)
Socket.close() 關(guān)閉連接

WebSocket實(shí)踐

前面介紹了在瀏覽器端webSocket的相關(guān)知識點(diǎn),現(xiàn)在我們就來搭建一個后臺對接應(yīng)用,以實(shí)現(xiàn)一個簡單的在線聊天室。

一點(diǎn)知識

后端關(guān)于WebSocket的實(shí)現(xiàn)是基于JSR356標(biāo)準(zhǔn)的。該標(biāo)準(zhǔn)的出現(xiàn),統(tǒng)一了
WebSocket的代碼寫法。只要支持web容器支持JSR356標(biāo)準(zhǔn),那么實(shí)現(xiàn)方式是一致的。而目前實(shí)現(xiàn)方式有兩種,一種是注解方式,另一種就是繼承繼承javax.websocket.Endpoint類了。

常用注解說明

  • @WebSocketEndpoint
    注解是一個類層次的注解,它的功能主要是將目前的類定義成一個websocket服務(wù)器端。注解的值將被用于監(jiān)聽用戶連接的終端訪問URL地址。
  • @onOpen
    打開一個新連接,即有新連接時,會調(diào)用被此注解的方法。
  • @onClose
    關(guān)閉連接時調(diào)用。
  • @onMessage
    當(dāng)服務(wù)器接收到客戶端發(fā)送的消息時所調(diào)用的方法。
  • @PathParam
    接收uri參數(shù)的,與@PathVariable功能差不多,可通過url獲取對應(yīng)值

搭建一個簡易聊天室

0.加入POM依賴。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

1.編寫控制層,對應(yīng)WebSocket的各事件。同時抽取了個公用類,進(jìn)行通用方法調(diào)用。

WebSocketController.java

/**
 * websocket 簡易聊天
 * @author oKong
 *
 */
//由于是websocket 所以原本是@RestController的http形式 
//直接替換成@ServerEndpoint即可,作用是一樣的 就是指定一個地址
//表示定義一個websocket的Server端
@Component
@ServerEndpoint(value = "/my-chat/{usernick}")
@Slf4j
public class WebSocketController {
	
	/**
	 * 連接事件 加入注解
	 * @param session
	 */
	@OnOpen
	public void onOpen(@PathParam(value = "usernick") String userNick,Session session) {
		String message = "有新游客[" + userNick + "]加入聊天室!";
		log.info(message);
		WebSocketUtil.addSession(userNick, session);	
		//此時可向所有的在線通知 某某某登錄了聊天室			
		WebSocketUtil.sendMessageForAll(message);
	}
	
	@OnClose
	public void onClose(@PathParam(value = "usernick") String userNick,Session session) {
		String message = "游客[" + userNick + "]退出聊天室!";
		log.info(message);
		WebSocketUtil.remoteSession(userNick);	
		//此時可向所有的在線通知 某某某登錄了聊天室			
		WebSocketUtil.sendMessageForAll(message);
	}
	
	@OnMessage
	public void OnMessage(@PathParam(value = "usernick") String userNick, String message) {
		//類似群發(fā)
		String info = "游客[" + userNick + "]:" + message;
		log.info(info);
		WebSocketUtil.sendMessageForAll(message);
	} 
	
	@OnError
	public void onError(Session session, Throwable throwable) {
		log.error("異常:", throwable);
		try {
			session.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		throwable.printStackTrace();
	}

}

WebSocketUtil.java

public class WebSocketUtil {

	/**
	 * 簡單使用map進(jìn)行存儲在線的session
	 * 
	 */
    private static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<>();
    
    public static void addSession(String userNick,Session session) {
    	//putIfAbsent 添加鍵—值對的時候,先判斷該鍵值對是否已經(jīng)存在
    	//不存在:新增,并返回null
    	//存在:不覆蓋,直接返回已存在的值
//    	ONLINE_SESSION.putIfAbsent(userNick, session);
    	//簡單示例 不考慮復(fù)雜情況。。怎么簡單怎么來了。。
    	ONLINE_SESSION.put(userNick, session);
    }
    
    public static void remoteSession(String userNick) {
    	ONLINE_SESSION.remove(userNick);
    }
    
    /**
     * 向某個用戶發(fā)送消息
     * @param session 某一用戶的session對象
     * @param message
     */
    public static void sendMessage(Session session, String message) {
    	if(session == null) {
    		return;
    	}
    	// getAsyncRemote()和getBasicRemote()異步與同步
    	Async async = session.getAsyncRemote();
    	//發(fā)送消息
    	async.sendText(message);
    }
    
    /**
     * 向所有在線人發(fā)送消息
     * @param message
     */
    public static void sendMessageForAll(String message) {
    	//jdk8 新方法
    	ONLINE_SESSION.forEach((sessionId, session) -> sendMessage(session, message));
    }
}

注意點(diǎn):

  • @ServerEndpoint的value值填寫時,開頭需要加上/,不然會提示路徑無效。
  • 需要加上類型@Component注解,使得能被掃描到。
  • 這里的session等,都在包javax.websocket包下的,注意區(qū)分。

2.編寫主啟動類,主要是加入注解@EnableWebSocket和申明一個Websocket endpoint類。

@SpringBootApplication
@EnableWebSocket
@Slf4j
public class Chapter19Application {

	public static void main(String[] args) {
		SpringApplication.run(Chapter19Application.class, args);
		log.info("Chapter19啟動!");
	}
	
	/**
	 * 會自動注冊使用了@ServerEndpoint注解聲明的Websocket endpoint
	 * 要注意,如果使用獨(dú)立的servlet容器,
	 * 而不是直接使用springboot的內(nèi)置容器,
	 * 就不要注入ServerEndpointExporter,因?yàn)樗鼘⒂扇萜髯约禾峁┖凸芾怼?	 */
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}
}

3.啟動應(yīng)用,利用在線的測試工具進(jìn)行測試。這里直接使用了http://coolaf.com/tool/chattest進(jìn)行測試。當(dāng)然也可以自己寫一個html了。

首先,輸入我們的服務(wù)地址:ws://127.0.0.1:8080/my-chat/okong,連接后就可以看見服務(wù)器返回的消息了。

加入加入

我們再開一個標(biāo)簽頁,然后繼續(xù)以另一個身份進(jìn)入:

新游客加入新游客加入

這時,可以看見第一個頁面開的,也收到消息了,F(xiàn)在我們發(fā)送一條消息:

發(fā)送消息發(fā)送消息

然后,其中一個斷開連接:

斷開連接

斷開連接

然后可以愉快聊天了,簡單的一個聊天室就完成了。

參考資料

  1. https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference/htmlsingle/#websocket
  2. https://docs.spring.io/spring-boot/docs/1.5.15.RELEASE/reference/htmlsingle/#boot-features-websockets
  3. http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html
  4. http://www.runoob.com/html/html5-websocket.html

總結(jié)

本章節(jié)主要是講解了WebSocket的使用。因?yàn)橛薪y(tǒng)一標(biāo)準(zhǔn)的存在,編寫webSocket也是很簡單的。對于如何一對一聊天,大家可以自行編寫下,因?yàn)橹懒藢Ψ矫Q,就能找出對方的session然后就能發(fā)送消息了。

最后

目前互聯(lián)網(wǎng)上很多大佬都有SpringBoot系列教程,如有雷同,請多多包涵了。本文是作者在電腦前一字一句敲的,每一步都是自己實(shí)踐的。若文中有所錯誤之處,還望提出,謝謝。

  • 個人博客:http://blog.lqdev.cn
  • 完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-19

標(biāo)簽: 代碼 服務(wù)器 服務(wù)器端 互聯(lián)網(wǎng) 通信

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:SpringBoot | 第二十章:異步開發(fā)之異步請求

下一篇:如果非得了解下 git 系統(tǒng)… – 實(shí)踐篇