之前公司的某個系統為了實現推送技術,所用的技術都是Ajax輪詢,這種方式瀏覽器需要不斷的向服務器發出請求,顯然這樣會浪費很多的帶寬等資源,所以研究了下WebSocket,本文將詳細介紹下。
一、什麼是WebSocket?
WebSocket是HTML5開始提供的一種在單個TCP連接上進行全雙工通訊的協議,能更好的節省服務器資源和帶寬,並且能夠更實時地進行通訊。
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據,在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。
二、SpringBoot整合WebSocket
新建一個spring boot項目spring-boot-websocket,按照下面步驟操作。
- pom.xml引入jar包
<code><dependency> <groupid>org.springframework.boot/<groupid> <artifactid>spring-boot-starter-websocket/<artifactid>/<dependency>/<code>
- 新建WebSocket的配置類
這個配置類檢測帶註解@ServerEndpoint的bean並註冊它們,配置類代碼如下:
<code>@Configurationpublic class WebSocketConfig { /** * 給spring容器注入這個ServerEndpointExporter對象 * 相當於xml: * <beans> * <bean> * /<beans> ** 檢測所有帶有@serverEndpoint註解的bean並註冊他們。 * * @return */ @Bean public ServerEndpointExporter serverEndpointExporter() { System.out.println("我被注入了"); return new ServerEndpointExporter(); }}
/<code>
- 新建WebSocket的處理類
這個處理類需要使用@ServerEndpoint,這個類裡監聽連接的建立關閉、消息的接收等,具體代碼如下:
<code>@ServerEndpoint(value = "/ws/asset")@Componentpublic class WebSocketServer { @PostConstruct public void init() { System.out.println("websocket 加載"); } private static Logger log = LoggerFactory.getLogger(WebSocketServer.class); private static final AtomicInteger OnlineCount = new AtomicInteger(0); // concurrent包的線程安全Set,用來存放每個客戶端對應的Session對象。 private static CopyOnWriteArraySet<session> SessionSet = new CopyOnWriteArraySet<session>(); /** * 連接建立成功調用的方法 */ @OnOpen public void onOpen(Session session) { SessionSet.add(session); int cnt = OnlineCount.incrementAndGet(); // 在線數加1 log.info("有連接加入,當前連接數為:{}", cnt); SendMessage(session, "連接成功"); } /** * 連接關閉調用的方法 */ @OnClose public void onClose(Session session) { SessionSet.remove(session); int cnt = OnlineCount.decrementAndGet(); log.info("有連接關閉,當前連接數為:{}", cnt); } /** * 收到客戶端消息後調用的方法 * * @param message * 客戶端發送過來的消息 */ @OnMessage public void onMessage(String message, Session session) { log.info("來自客戶端的消息:{}",message); SendMessage(session, "收到消息,消息內容:"+message); } /** * 出現錯誤 * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { log.error("發生錯誤:{},Session ID: {}",error.getMessage(),session.getId()); error.printStackTrace(); } /** * 發送消息,實踐表明,每次瀏覽器刷新,session會發生變化。 * @param session * @param message */ public static void SendMessage(Session session, String message) { try {// session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId())); session.getBasicRemote().sendText(message); } catch (IOException e) { log.error("發送消息出錯:{}", e.getMessage()); e.printStackTrace(); } } /** * 群發消息 * @param message * @throws IOException */ public static void BroadCastInfo(String message) throws IOException { for (Session session : SessionSet) { if(session.isOpen()){ SendMessage(session, message); } } } /** * 指定Session發送消息 * @param sessionId * @param message * @throws IOException */ public static void SendMessage(String message,String sessionId) throws IOException { Session session = null; for (Session s : SessionSet) { if(s.getId().equals(sessionId)){ session = s; break; } } if(session!=null){ SendMessage(session, message); } else{ log.warn("沒有找到你指定ID的會話:{}",sessionId); } }}/<session>/<session>/<code>
- 新建一個html
目前大部分瀏覽器支持WebSocket,比如Chrome, Mozilla,Opera和Safari,在html頁面進行websocket的連接建立、收消息的監聽,頁面代碼如下:
<code> <title>websocket測試/<title> <style> h3,h4{ text-align:center; } /<style>WebSocket測試,客戶端接收到的消息如下:
<textarea>