以前用.net的一個開源框架寫了WebSocket的應用,恰好pmgo有用到。現現在須要本身作一個簡易聊天室,前端也寫了一些,服務端打算用Java(.netcore擼了一天,都沒看出個因此然來,連WebSocket的端口都不知道怎麼設置ಥ_ಥ,雖然下面這個Demo也沒有找到如何設置。)下面就動手實操吧前端
1、pom.xml引入包web
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
在依賴中添加如上代碼段,引入websocket包。spring
2、WebSocketUtil後端
接下來建立一個WebSocketUtil類,用於提供對session連接、斷開鏈接、推送消息的簡單控制。springboot
(注:此處的sendMessage,直接將字符串消息推送給客戶端。現下前後端分離的應用,都採用Json數據傳輸標準,因此後期最好將其封裝爲標準的Json對象)websocket
public class WebsocketUtil { /** * 記錄當前在線的Session */ private static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<> (); /** * 添加session * @param userId * @param session */ public static void addSession(String userId, Session session){ // 此處只容許一個用戶的session連接。一個用戶的多個鏈接,咱們視爲無效。 ONLINE_SESSION.putIfAbsent ( userId, session ); } /** * 關閉session * @param userId */ public static void removeSession(String userId){ ONLINE_SESSION.remove ( userId ); } /** * 給單個用戶推送消息 * @param session * @param message */ public static void sendMessage(Session session, String message){ if(session == null){ return; } // 同步 RemoteEndpoint.Async async = session.getAsyncRemote (); async.sendText ( message ); } /** * 向全部在線人發送消息 * @param message */ public static void sendMessageForAll(String message) { //jdk8 新方法 ONLINE_SESSION.forEach((sessionId, session) -> sendMessage(session, message)); } }
3、WebSocketControllersession
如上,已經建立好了簡單的session管理和消息管理,接下來要使用註解的方式,使用SpringBoot的websocket包提供的方法,實現OnOpen、OnClose、OnMessage三個方法,再實現一個OnError方法來應對異常。代碼段以下:框架
/** * websocket接口處理類 */ @Component @ServerEndpoint ( value = "/chat/{userid}" ) public class WebsocketController { /** * 鏈接事件,加入註解 * @param userId * @param session */ @OnOpen public void onOpen( @PathParam ( value = "userid" ) String userId, Session session ) { String message ="[" + userId + "]加入聊天室!!"; // 添加到session的映射關係中 WebsocketUtil.addSession ( userId, session ); // 廣播通知,某用戶上線了 WebsocketUtil.sendMessageForAll ( message ); } /** * 鏈接事件,加入註解 * 用戶斷開連接 * @param userId * @param session */ @OnClose public void onClose(@PathParam ( value = "userId" ) String userId, Session session ) { String message ="[" + userId + "]退出了聊天室..."; // 刪除映射關係 WebsocketUtil.removeSession ( userId ); // 廣播通知,用戶下線了 WebsocketUtil.sendMessageForAll ( message ); } /** * 當接收到用戶上傳的消息 * @param userId * @param session */ @OnMessage public void onMessage(@PathParam ( value = "userId" ) String userId, Session session ,String message) { String msg ="[" + userId + "]:"+message; // 直接廣播 WebsocketUtil.sendMessageForAll ( msg ); } /** * 處理用戶活鏈接異常 * @param session * @param throwable */ @OnError public void onError(Session session, Throwable throwable) { try { session.close(); } catch (IOException e) { e.printStackTrace(); } throwable.printStackTrace(); } }
到此基本完成了websocket的服務。socket
4、添加 ServerEndpointExporter 啓動Beanasync
修改main函數所在的啓動方法代碼段,添加 serverEndpointExporter :
public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } /** * 會自動註冊使用了@ServerEndpoint註解聲明的Websocket endpoint * 要注意,若是使用獨立的servlet容器, * 而不是直接使用springboot的內置容器, * 就不要注入ServerEndpointExporter,由於它將由容器本身提供和管理。 */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
至此,完成了全部代碼的編寫。
5、測試
使用 http://coolaf.com/tool/chattest 這個站點,來測試連接。首先啓動項目,啓動後,點開網址輸入應用的WebSocket連接url:ws://127.0.0.1:5088/chat/user1 測試連接