程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 基於Spring 4.0 的 Web Socket,springsocket

基於Spring 4.0 的 Web Socket,springsocket

編輯:JAVA綜合教程

基於Spring 4.0 的 Web Socket,springsocket


在現在很多業務場景(比如聊天室),又或者是手機端的一些online游戲,都需要做到實時通信,那怎麼來進行雙向通信呢,總不見得用曾經很破舊的ajax每隔10秒或者每隔20秒來請求吧,我的天吶,這尼瑪太坑了

跟webservice來相比,Web Socket可以做到保持長連接,或者說強連接,一直握手存在兩端可以互相發送消息互相收到消息,而webservice是一次性的,你要我響應就必須要請求我一次

注:浏覽器需要使用高版本的chrome或者Firefox,Tomcat使用8

先借用一下知乎某大神的原文:

作者:Ovear
鏈接:http://www.zhihu.com/question/20215561/answer/40316953
來源:知乎

一、WebSocket是HTML5出的東西(協議),也就是說HTTP協議沒有變化,或者說沒關系,但HTTP是不支持持久連接的(長連接,循環連接的不算)
首先HTTP有1.1和1.0之說,也就是所謂的keep-alive,把多個HTTP請求合並為一個,但是Websocket其實是一個新協議,跟HTTP協議基本沒有關系,只是為了兼容現有浏覽器的握手規范而已,也就是說它是HTTP協議上的一種補充可以通過這樣一張圖理解
有交集,但是並不是全部。
另外Html5是指的一系列新的API,或者說新規范,新技術。Http協議本身只有1.0和1.1,而且跟Html本身沒有直接關系。。
通俗來說,你可以用HTTP協議傳輸非Html數據,就是這樣=。=
再簡單來說,層級不一樣

二、Websocket是什麼樣的協議,具體有什麼優點
首先,Websocket是一個持久化的協議,相對於HTTP這種非持久的協議來說。
簡單的舉個例子吧,用目前應用比較廣泛的PHP生命周期來解釋。
1) HTTP的生命周期通過Request來界定,也就是一個Request 一個Response,那麼HTTP1.0,這次HTTP請求就結束了。
在HTTP1.1中進行了改進,使得有一個keep-alive,也就是說,在一個HTTP連接中,可以發送多個Request,接收多個Response。
但是請記住 Request = Response , 在HTTP中永遠是這樣,也就是說一個request只能有一個response。而且這個response也是被動的,不能主動發起。

教練,你BB了這麼多,跟Websocket有什麼關系呢?
_(:з」∠)_好吧,我正准備說Websocket呢。。
首先Websocket是基於HTTP協議的,或者說借用了HTTP的協議來完成一部分握手。
在握手階段是一樣的
-------以下涉及專業技術內容,不想看的可以跳過lol:,或者只看加黑內容--------
首先我們來看個典型的Websocket握手(借用Wikipedia的。。)
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
熟悉HTTP的童鞋可能發現了,這段類似HTTP協議的握手請求中,多了幾個東西。
我會順便講解下作用。
Upgrade: websocket
Connection: Upgrade
這個就是Websocket的核心了,告訴Apache、Nginx等服務器:注意啦,窩發起的是Websocket協議,快點幫我找到對應的助理處理~不是那個老土的HTTP。
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
首先,Sec-WebSocket-Key 是一個Base64 encode的值,這個是浏覽器隨機生成的,告訴服務器:泥煤,不要忽悠窩,我要驗證尼是不是真的是Websocket助理。
然後,Sec_WebSocket-Protocol 是一個用戶定義的字符串,用來區分同URL下,不同的服務所需要的協議。簡單理解:今晚我要服務A,別搞錯啦~
最後,Sec-WebSocket-Version 是告訴服務器所使用的Websocket Draft(協議版本),在最初的時候,Websocket協議還在 Draft 階段,各種奇奇怪怪的協議都有,而且還有很多期奇奇怪怪不同的東西,什麼Firefox和Chrome用的不是一個版本之類的,當初Websocket協議太多可是一個大難題。。不過現在還好,已經定下來啦~大家都使用的一個東西~ 脫水:服務員,我要的是13歲的噢→_→

然後服務器會返回下列東西,表示已經接受到請求, 成功建立Websocket啦!
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
這裡開始就是HTTP最後負責的區域了,告訴客戶,我已經成功切換協議啦~
Upgrade: websocket
Connection: Upgrade
依然是固定的,告訴客戶端即將升級的是Websocket協議,而不是mozillasocket,lurnarsocket或者shitsocket。
然後,Sec-WebSocket-Accept 這個則是經過服務器確認,並且加密過後的 Sec-WebSocket-Key。服務器:好啦好啦,知道啦,給你看我的ID CARD來證明行了吧。。
後面的,Sec-WebSocket-Protocol 則是表示最終使用的協議。

至此,HTTP已經完成它所有工作了,接下來就是完全按照Websocket協議進行了。
具體的協議就不在這闡述了。
------------------技術解析部分完畢------------------

你TMD又BBB了這麼久,那到底Websocket有什麼鬼用,http long poll,或者ajax輪詢不都可以實現實時信息傳遞麼。


好好好,年輕人,那我們來講一講Websocket有什麼用。
來給你吃點胡(蘇)蘿(丹)卜(紅)
三、Websocket的作用
在講Websocket之前,我就順帶著講下 long poll 和 ajax輪詢 的原理。
首先是 ajax輪詢 ,ajax輪詢 的原理非常簡單,讓浏覽器隔個幾秒就發送一次請求,詢問服務器是否有新信息。
場景再現:
客戶端:啦啦啦,有沒有新信息(Request)
服務端:沒有(Response)
客戶端:啦啦啦,有沒有新信息(Request)
服務端:沒有。。(Response)
客戶端:啦啦啦,有沒有新信息(Request)
服務端:你好煩啊,沒有啊。。(Response)
客戶端:啦啦啦,有沒有新消息(Request)
服務端:好啦好啦,有啦給你。(Response)
客戶端:啦啦啦,有沒有新消息(Request)
服務端:。。。。。沒。。。。沒。。。沒有(Response) ---- loop

long poll
long poll 其實原理跟 ajax輪詢 差不多,都是采用輪詢的方式,不過采取的是阻塞模型(一直打電話,沒收到就不掛電話),也就是說,客戶端發起連接後,如果沒消息,就一直不返回Response給客戶端。直到有消息才返回,返回完之後,客戶端再次建立連接,周而復始。
場景再現
客戶端:啦啦啦,有沒有新信息,沒有的話就等有了才返回給我吧(Request)
服務端:額。。 等待到有消息的時候。。來 給你(Response)
客戶端:啦啦啦,有沒有新信息,沒有的話就等有了才返回給我吧(Request) -loop

從上面可以看出其實這兩種方式,都是在不斷地建立HTTP連接,然後等待服務端處理,可以體現HTTP協議的另外一個特點,被動性
何為被動性呢,其實就是,服務端不能主動聯系客戶端,只能有客戶端發起。
簡單地說就是,服務器是一個很懶的冰箱(這是個梗)(不會、不能主動發起連接),但是上司有命令,如果有客戶來,不管多麼累都要好好接待。

說完這個,我們再來說一說上面的缺陷(原諒我廢話這麼多吧OAQ)
從上面很容易看出來,不管怎麼樣,上面這兩種都是非常消耗資源的。
ajax輪詢 需要服務器有很快的處理速度和資源。(速度)
long poll 需要有很高的並發,也就是說同時接待客戶的能力。(場地大小)
所以ajax輪詢 和long poll 都有可能發生這種情況。

客戶端:啦啦啦啦,有新信息麼?
服務端:月線正忙,請稍後再試(503 Server Unavailable)
客戶端:。。。。好吧,啦啦啦,有新信息麼?
服務端:月線正忙,請稍後再試(503 Server Unavailable)

客戶端:
然後服務端在一旁忙的要死:冰箱,我要更多的冰箱!更多。。更多。。(我錯了。。這又是梗。。)

--------------------------
言歸正傳,我們來說Websocket吧
通過上面這個例子,我們可以看出,這兩種方式都不是最好的方式,需要很多資源。
一種需要更快的速度,一種需要更多的'電話'。這兩種都會導致'電話'的需求越來越高。
哦對了,忘記說了HTTP還是一個無狀態協議。(感謝評論區的各位指出OAQ)
通俗的說就是,服務器因為每天要接待太多客戶了,是個健忘鬼,你一掛電話,他就把你的東西全忘光了,把你的東西全丟掉了。你第二次還得再告訴服務器一遍。

所以在這種情況下出現了,Websocket出現了。
他解決了HTTP的這幾個難題。
首先,被動性,當服務器完成協議升級後(HTTP->Websocket),服務端就可以主動推送信息給客戶端啦。
所以上面的情景可以做如下修改。
客戶端:啦啦啦,我要建立Websocket協議,需要的服務:chat,Websocket協議版本:17(HTTP Request)
服務端:ok,確認,已升級為Websocket協議(HTTP Protocols Switched)
客戶端:麻煩你有信息的時候推送給我噢。。
服務端:ok,有的時候會告訴你的。
服務端:balabalabalabala
服務端:balabalabalabala
服務端:哈哈哈哈哈啊哈哈哈哈
服務端:笑死我了哈哈哈哈哈哈哈

就變成了這樣,只需要經過一次HTTP請求,就可以做到源源不斷的信息傳送了。(在程序設計中,這種設計叫做回調,即:你有信息了再來通知我,而不是我傻乎乎的每次跑來問你)
這樣的協議解決了上面同步有延遲,而且還非常消耗資源的這種情況。
那麼為什麼他會解決服務器上消耗資源的問題呢?
其實我們所用的程序是要經過兩層代理的,即HTTP協議在Nginx等服務器的解析下,然後再傳送給相應的Handler(PHP等)來處理。
簡單地說,我們有一個非常快速的接線員(Nginx),他負責把問題轉交給相應的客服(Handler)
本身接線員基本上速度是足夠的,但是每次都卡在客服(Handler)了,老有客服處理速度太慢。,導致客服不夠。
Websocket就解決了這樣一個難題,建立後,可以直接跟接線員建立持久連接,有信息的時候客服想辦法通知接線員,然後接線員在統一轉交給客戶。
這樣就可以解決客服處理速度過慢的問題了。

同時,在傳統的方式上,要不斷的建立,關閉HTTP協議,由於HTTP是非狀態性的,每次都要重新傳輸identity info(鑒別信息),來告訴服務端你是誰。
雖然接線員很快速,但是每次都要聽這麼一堆,效率也會有所下降的,同時還得不斷把這些信息轉交給客服,不但浪費客服的處理時間,而且還會在網路傳輸中消耗過多的流量/時間。
但是Websocket只需要一次HTTP握手,所以說整個通訊過程是建立在一次連接/狀態中,也就避免了HTTP的非狀態性,服務端會一直知道你的信息,直到你關閉請求,這樣就解決了接線員要反復解析HTTP協議,還要查看identity info的信息。
同時由客戶主動詢問,轉換為服務器(推送)有信息的時候就發送(當然客戶端還是等主動發送信息過來的。。),沒有信息的時候就交給接線員(Nginx),不需要占用本身速度就慢的客服(Handler)
--------------------
至於怎麼在不支持Websocket的客戶端上使用Websocket。。答案是:不能
但是可以通過上面說的 long poll 和 ajax 輪詢來 模擬出類似的效果


下面貼出我的代碼片段以及github地址 功能點:

spring websocket chating room
使用spring websocket實現聊天室基本功能
1.群發消息給所有人
2.悄悄話給某個人

效果: 主要代碼: pom.xml引入必要的庫
  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  4     <modelVersion>4.0.0</modelVersion>
  5     <groupId>com.lee</groupId>
  6     <artifactId>websocket</artifactId>
  7     <name>maven-spring-websocket-01</name>
  8     <packaging>war</packaging>
  9     <version>1.0.0-BUILD-SNAPSHOT</version>
 10 
 11     <properties>
 12         
 13         <java.version>1.7</java.version>
 14         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 15         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 16         
 17         <spring.version>4.0.0.RELEASE</spring.version>
 18         
 19         <junit.version>4.11</junit.version>
 20         
 21         <!-- Logging -->
 22         <logback.version>1.0.13</logback.version>
 23         <slf4j.version>1.7.7</slf4j.version>
 24     </properties>
 25 
 26     <dependencies>
 27         <!--spring MVC -->
 28         <dependency>
 29             <groupId>org.springframework</groupId>
 30             <artifactId>spring-core</artifactId>
 31             <version>${spring.version}</version>
 32         </dependency>
 33 
 34         <dependency>
 35             <groupId>org.springframework</groupId>
 36             <artifactId>spring-web</artifactId>
 37             <version>${spring.version}</version>
 38         </dependency>
 39 
 40         <dependency>
 41             <groupId>org.springframework</groupId>
 42             <artifactId>spring-webmvc</artifactId>
 43             <version>${spring.version}</version>
 44         </dependency>
 45 
 46         <!-- jstl -->
 47         <dependency>
 48             <groupId>jstl</groupId>
 49             <artifactId>jstl</artifactId>
 50             <version>1.2</version>
 51         </dependency>
 52 
 53         <!--spring測試框架 -->
 54         <dependency>
 55             <groupId>org.springframework</groupId>
 56             <artifactId>spring-test</artifactId>
 57             <version>${spring.version}</version>
 58             <scope>test</scope>
 59         </dependency>
 60 
 61         <!--spring數據庫操作庫 -->
 62         <dependency>
 63             <groupId>org.springframework</groupId>
 64             <artifactId>spring-jdbc</artifactId>
 65             <version>${spring.version}</version>
 66         </dependency>
 67 
 68         <dependency>
 69             <groupId>junit</groupId>
 70             <artifactId>junit</artifactId>
 71             <version>4.8.2</version>
 72             <scope>test</scope>
 73         </dependency>
 74 
 75         <!--spring websocket庫 -->
 76         <dependency>
 77             <groupId>org.springframework</groupId>
 78             <artifactId>spring-websocket</artifactId>
 79             <version>${spring.version}</version>
 80         </dependency>
 81         <dependency>
 82             <groupId>org.springframework</groupId>
 83             <artifactId>spring-messaging</artifactId>
 84             <version>${spring.version}</version>
 85         </dependency>
 86 
 87         <!--jackson用於json操作 -->
 88         <dependency>
 89             <groupId>com.fasterxml.jackson.core</groupId>
 90             <artifactId>jackson-databind</artifactId>
 91             <version>2.3.0</version>
 92         </dependency>
 93 
 94         <dependency>
 95             <groupId>commons-fileupload</groupId>
 96             <artifactId>commons-fileupload</artifactId>
 97             <version>1.2.2</version>
 98         </dependency>
 99         <dependency>
100             <groupId>commons-io</groupId>
101             <artifactId>commons-io</artifactId>
102             <version>2.2</version>
103         </dependency>
104         
105         <!-- Logging with SLF4J & LogBack -->
106         <dependency>
107             <groupId>org.slf4j</groupId>
108             <artifactId>slf4j-api</artifactId>
109             <version>${slf4j.version}</version>
110             <scope>compile</scope>
111         </dependency>
112         <dependency>
113             <groupId>ch.qos.logback</groupId>
114             <artifactId>logback-classic</artifactId>
115             <version>${logback.version}</version>
116             <scope>runtime</scope>
117         </dependency>
118         
119         <!--使用阿裡的連接池 -->
120         <dependency>
121             <groupId>com.alibaba</groupId>
122             <artifactId>druid</artifactId>
123             <version>1.0.4</version>
124         </dependency>
125         
126         <!--mysql connector -->
127         <dependency>
128             <groupId>mysql</groupId>
129             <artifactId>mysql-connector-java</artifactId>
130             <version>5.1.29</version>
131         </dependency>
132 
133     </dependencies>
134     
135     <build>
136         <plugins>
137             <plugin>
138                 <groupId>org.apache.maven.plugins</groupId>
139                 <artifactId>maven-compiler-plugin</artifactId>
140                 <configuration>
141                     <source>1.7</source>
142                     <target>1.7</target>
143                 </configuration>
144             </plugin>
145         </plugins>
146     </build>
147     
148 </project>

主要結構

HandshakeInterceptor.java

 1 package com.lee.websocket;
 2 
 3 import java.util.Map;
 4 
 5 import javax.servlet.http.HttpSession;
 6 
 7 import org.springframework.http.server.ServerHttpRequest;
 8 import org.springframework.http.server.ServerHttpResponse;
 9 import org.springframework.http.server.ServletServerHttpRequest;
10 import org.springframework.web.socket.WebSocketHandler;
11 
12 public class HandshakeInterceptor implements org.springframework.web.socket.server.HandshakeInterceptor {
13 
14     //進入hander之前的攔截
15     @Override
16     public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
17         if (request instanceof ServletServerHttpRequest) {
18             ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
19             
20             String clientName = (String)servletRequest.getServletRequest().getParameter("name");
21             System.out.println(clientName);
22             
23             HttpSession session = servletRequest.getServletRequest().getSession(true);
24 //            String userName = "lee";
25             if (session != null) {
26                 //使用userName區分WebSocketHandler,以便定向發送消息
27 //                String clientName = (String) session.getAttribute("WEBSOCKET_USERNAME");
28                 map.put("WEBSOCKET_USERNAME", clientName);
29             }
30         }
31         return true;
32     }
33 
34     @Override
35     public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
36 
37     }
38     
39 }

 

HomeController.java

 1 package com.lee.websocket;
 2 
 3 import java.text.DateFormat;
 4 import java.util.Date;
 5 import java.util.Locale;
 6 
 7 import org.slf4j.Logger;
 8 import org.slf4j.LoggerFactory;
 9 import org.springframework.stereotype.Controller;
10 import org.springframework.ui.Model;
11 import org.springframework.web.bind.annotation.RequestMapping;
12 import org.springframework.web.bind.annotation.RequestMethod;
13 
14 /**
15  * Handles requests for the application home page.
16  */
17 @Controller
18 public class HomeController {
19     
20     private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
21     
22     /**
23      * Simply selects the home view to render by returning its name.
24      */
25     @RequestMapping(value = "/", method = RequestMethod.GET)
26     public String home(Locale locale, Model model) {
27         logger.info("Welcome home! The client locale is {}.", locale);
28         
29         Date date = new Date();
30         DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
31         
32         String formattedDate = dateFormat.format(date);
33         
34         model.addAttribute("serverTime", formattedDate );
35         
36         return "home";
37     }
38     
39     @RequestMapping(value = "/chat", method = RequestMethod.GET)
40     public String chat(Locale locale, Model model) {
41         return "chat";
42     }
43     
44 }

 

WebSocketConfig.java

 1 package com.lee.websocket;
 2 
 3 import org.springframework.context.annotation.Configuration;
 4 import org.springframework.web.socket.config.annotation.EnableWebSocket;
 5 import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
 6 import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
 7 
 8 @Configuration
 9 @EnableWebSocket//開啟websocket
10 public class WebSocketConfig implements WebSocketConfigurer {
11     @Override
12     public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
13         registry.addHandler(new WebSocketHander(),"/echo").addInterceptors(new HandshakeInterceptor()); //支持websocket 的訪問鏈接
14         registry.addHandler(new WebSocketHander(),"/sockjs/echo").addInterceptors(new HandshakeInterceptor()).withSockJS(); //不支持websocket的訪問鏈接
15     }
16 }


WebSocketHander.java

  1 package com.lee.websocket;
  2 
  3 import java.io.IOException;
  4 import java.util.ArrayList;
  5 
  6 import org.slf4j.Logger;
  7 import org.slf4j.LoggerFactory;
  8 import org.springframework.web.socket.CloseStatus;
  9 import org.springframework.web.socket.TextMessage;
 10 import org.springframework.web.socket.WebSocketHandler;
 11 import org.springframework.web.socket.WebSocketMessage;
 12 import org.springframework.web.socket.WebSocketSession;
 13 
 14 public class WebSocketHander implements WebSocketHandler {
 15     private static final Logger logger = LoggerFactory.getLogger(WebSocketHander.class);
 16 
 17     private static final ArrayList<WebSocketSession> users = new ArrayList<>();
 18 
 19     //初次鏈接成功執行
 20     @Override
 21     public void afterConnectionEstablished(WebSocketSession session) throws Exception {
 22         logger.debug("鏈接成功......");
 23         users.add(session);
 24         String userName = (String) session.getHandshakeAttributes().get("WEBSOCKET_USERNAME");
 25         if(userName!= null){
 26             session.sendMessage(new TextMessage("歡迎來到Nathan的聊天室,我們開始聊天吧!~"));
 27         }
 28     }
 29 
 30     //接受消息處理消息
 31     @Override
 32     public void handleMessage(WebSocketSession session, WebSocketMessage<?> webSocketMessage) throws Exception {
 33         String clientName = (String) session.getHandshakeAttributes().get("WEBSOCKET_USERNAME");
 34         
 35         clientName = "<a onclick='changeChater(this)'>" + clientName + "</a>";
 36             
 37         String msg = webSocketMessage.getPayload().toString();
 38         String charter = "";
 39         
 40         String msgs[] = msg.split("\\|");
 41         if (msgs.length > 1) {
 42             msg = msgs[1];
 43             charter = msgs[0];
 44             sendMessageToUser(charter, new TextMessage(clientName + "  悄悄地對你說 :" + msg));
 45         } else {
 46             sendMessageToUsers(new TextMessage(clientName + "  說:" + msg));
 47         }
 48         
 49     }
 50 
 51     @Override
 52     public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
 53         if(webSocketSession.isOpen()){
 54             webSocketSession.close();
 55         }
 56         logger.debug("鏈接出錯,關閉鏈接......");
 57         users.remove(webSocketSession);
 58     }
 59 
 60     @Override
 61     public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
 62         logger.debug("鏈接關閉......" + closeStatus.toString());
 63         users.remove(webSocketSession);
 64     }
 65 
 66     @Override
 67     public boolean supportsPartialMessages() {
 68         return false;
 69     }
 70     
 71     /**
 72      * 給所有在線用戶發送消息
 73      *
 74      * @param message
 75      */
 76     public void sendMessageToUsers(TextMessage message) {
 77         for (WebSocketSession user : users) {
 78             try {
 79                 if (user.isOpen()) {
 80                     user.sendMessage(message);
 81                 }
 82             } catch (IOException e) {
 83                 e.printStackTrace();
 84             }
 85         }
 86     }
 87 
 88     /**
 89      * 給某個用戶發送消息
 90      *
 91      * @param userName
 92      * @param message
 93      */
 94     public void sendMessageToUser(String userName, TextMessage message) {
 95         for (WebSocketSession user : users) {
 96             if (user.getHandshakeAttributes().get("WEBSOCKET_USERNAME").equals(userName)) {
 97                 try {
 98                     if (user.isOpen()) {
 99                         user.sendMessage(message);
100                     }
101                 } catch (IOException e) {
102                     e.printStackTrace();
103                 }
104                 break;
105             }
106         }
107     }
108 }

 

Person.java
 1 package com.lee.websocket.entity;
 2 
 3 public class Person {
 4 
 5     private int age;
 6     private String name;
 7     private String sex;
 8     
 9     public int getAge() {
10         return age;
11     }
12     public void setAge(int age) {
13         this.age = age;
14     }
15     public String getName() {
16         return name;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     public String getSex() {
22         return sex;
23     }
24     public void setSex(String sex) {
25         this.sex = sex;
26     }
27     
28 }

chat.jsp

  1 <%@ page contentType="text/html; charset=utf-8" language="java" %>
  2 <html>
  3 <head lang="en">
  4     <meta charset="UTF-8">
  5     <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
  6     <!-- 新 Bootstrap 核心 CSS 文件 -->
  7     <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
  8     <!-- 可選的Bootstrap主題文件(一般不用引入) -->
  9     <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
 10     <!-- jQuery文件。務必在bootstrap.min.js 之前引入 -->
 11     <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
 12     <!--<script type="text/javascript" src="js/jquery-1.7.2.js"></script>-->
 13     <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
 14     <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
 15     <title>webSocket測試</title>
 16     <script type="text/javascript">
 17         var chater;
 18         
 19         $(function(){
 20             
 21             var websocket;
 22             function connectServer() {
 23                 var clientName = $("#client_name").val();
 24                 if ("WebSocket" in window) {
 25                     websocket = new WebSocket("ws://127.0.0.1:8080/websocket/echo?name=" + clientName);
 26                 } else if ("MozWebSocket" in window) {
 27                     alert("MozWebSocket");
 28                     websocket = new MozWebSocket("ws://echo");
 29                 } else {
 30                     alert("SockJS");
 31                     websocket = new SockJS("http://127.0.0.1:8080/websocket/sockjs/echo");
 32                 }
 33             }
 34             
 35 //             websocket.onopen = function (evnt) {
 36 //                 $("#tou").html("鏈接服務器成功!")
 37 //             };
 38 //             websocket.onmessage = function (evnt) {
 39 //                 $("#msg").html($("#msg").html() + "<br/>" + evnt.data);
 40 //             };
 41 //             websocket.onerror = function (evnt) {
 42 //             };
 43 //             websocket.onclose = function (evnt) {
 44 //                 $("#tou").html("與服務器斷開了鏈接!")
 45 //             }
 46             
 47             $("#conncet_server").bind("click", function() {
 48                 connectServer();
 49                 
 50                 websocket.onopen = function (evnt) {
 51                     $("#tou").html("鏈接服務器成功!")
 52                 };
 53                 websocket.onmessage = function (evnt) {
 54                     $("#msg").html($("#msg").html() + "<br/>" + evnt.data);
 55                 };
 56                 websocket.onerror = function (evnt) {
 57                 };
 58                 websocket.onclose = function (evnt) {
 59                     $("#tou").html("與服務器斷開了鏈接!")
 60                 }
 61             });
 62             
 63             $("#send").bind("click", function() {
 64                 send();
 65             });
 66             
 67             function send(){
 68                 if (websocket != null) {
 69                     var message = document.getElementById("message").value;
 70                     
 71                     if ($.trim(chater) != "") {
 72                         message = chater + "|" + message;
 73                     }
 74                     
 75                     websocket.send(message);
 76                 } else {
 77                     alert("未與服務器鏈接.");
 78                 }
 79             }
 80         });
 81         
 82         function changeChater(e) {
 83             chater = $(e).html();
 84             alert("您將和" + chater + "進行聊天...");
 85         }
 86     </script>
 87 
 88 </head>
 89 <body>
 90 
 91     <div class="page-header" id="tou">webSocket及時聊天Demo程序</div>
 92     <div class="well" id="msg"></div>
 93     <div class="col-lg">
 94         <div class="input-group">
 95             <input type="text" class="form-control" placeholder="請輸入用戶名..." id="client_name"> 
 96             <span class="input-group-btn">
 97                 <button class="btn btn-default" type="button" id="conncet_server">連接服務器</button>
 98             </span>
 99         </div>
100     </div>
101     
102     <br/>
103     
104     <div class="col-lg">
105         <div class="input-group">
106             <input type="text" class="form-control" placeholder="發送信息..." id="message"> 
107             <span class="input-group-btn">
108                 <button class="btn btn-default" type="button" id="send">發送</button>
109             </span>
110         </div>
111     </div>
112 </body>
113 
114 </html>

 

  有興趣的朋友可以關注github地址:https://github.com/leechenxiang/maven-spring-websocket-01

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved