java实现聊天室(websocket)
生活随笔
收集整理的這篇文章主要介紹了
java实现聊天室(websocket)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
引入依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.1.3.RELEASE</version></dependency>Controller層,打開聊天室界面
import com.shangfei.response.WebResponse; import com.shangfei.service.socket.WebSocketService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView;/*** @authoer:majinzhong* @Date: 2022/11/7* @Description: websocket的具體實現類* 使用springboot的唯一區別是要@Component聲明下,而使用獨立容器是由容器自己管理websocket的,* 但在springboot中連容器都是spring管理的。* 雖然@Component默認是單例模式的,但springboot還是會為每個websocket連接初始化一個bean,* 所以可以用一個靜態set保存起來。*/@RestController public class WebSocketController {@AutowiredWebSocketService webSocketService;/*** 打開發送消息頁面* @return*/@RequestMapping("/webSocketPage")public ModelAndView page(){return new ModelAndView("index");}/*** 獲得在線人信息* @return*/@RequestMapping("/members")public WebResponse members(){return webSocketService.members();}}Service層,實時監聽并轉發消息
import cn.hutool.core.collection.CollectionUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.shangfei.mapper.plan.UserMapper; import com.shangfei.pojo.socket.SocketMsg; import com.shangfei.response.WebResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.CrossOrigin;import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.*; import java.util.concurrent.CopyOnWriteArraySet;/*** @authoer:majinzhong* @Date: 2022/11/16* @description:*/ @Component @ServerEndpoint(value = "/websocket/{nickname}") @CrossOrigin @Service public class WebSocketService {@AutowiredUserMapper userMapper;/*** 用來存放每個客戶端對應的MyWebSocket對象。**/private static CopyOnWriteArraySet<WebSocketService> webSocketSet = new CopyOnWriteArraySet<>();/*** 與某個客戶端的連接會話,需要通過它來給客戶端發送數據**/private Session session;/*** 用戶名稱**/private String nickname;/*** 用來記錄sessionId和該session進行綁定**/private static Map<String,Session> map = new HashMap<String, Session>();public WebResponse members(){Set<String> members = map.keySet();if(!CollectionUtil.isEmpty(members)) {List<Map<String,String>> userList=new ArrayList<>();for(String member:members){//通過工號查詢名字Map<String, String> user = userMapper.selectName(member);if(!CollectionUtil.isEmpty(user)){userList.add(user);}else{Map<String, String> userMap = new HashMap<>();userMap.put("username",member);userMap.put("name","");userList.add(userMap);}}return WebResponse.success(userList);}else{return WebResponse.success(members);}}/*** 連接建立成功調用的方法*/@OnOpenpublic void onOpen(Session session,@PathParam("nickname") String nickname) {this.session = session;this.nickname=nickname;map.put(nickname, session);webSocketSet.add(this);System.out.println("有新連接加入:"+nickname+",當前在線人數為" + webSocketSet.size());this.session.getAsyncRemote().sendText("恭喜:"+nickname+" 成功連接上WebSocket(其頻道號:"+session.getId()+")-->當前在線人數為:"+webSocketSet.size());}/*** 連接關閉調用的方法*/@OnClosepublic void onClose() {webSocketSet.remove(this);List<String> nickname = this.session.getRequestParameterMap().get("nickname");for(String nick:nickname) {map.remove(nick);}System.out.println("有一連接關閉!當前在線人數為" + webSocketSet.size());}/*** 收到客戶端消息后調用的方法*/@OnMessagepublic void onMessage(String message, Session session,@PathParam("nickname") String nickname) {System.out.println("來自客戶端的消息-->"+nickname+": " + message);//從客戶端傳過來的數據是json數據,所以這里使用jackson進行轉換為SocketMsg對象,// 然后通過socketMsg的type進行判斷是單聊還是群聊,進行相應的處理:ObjectMapper objectMapper = new ObjectMapper();SocketMsg socketMsg;try {socketMsg = objectMapper.readValue(message, SocketMsg.class);if(socketMsg.getType() == 1){//單聊.需要找到發送者和接受者.socketMsg.setFromUser(nickname);Session fromSession = map.get(socketMsg.getFromUser());Session toSession = map.get(socketMsg.getToUser());//發送給接受者.if(toSession != null){//發送給發送者.fromSession.getAsyncRemote().sendText(nickname+"->"+toSession.getPathParameters().get("nickname")+":"+socketMsg.getMsg());toSession.getAsyncRemote().sendText(nickname+"->"+toSession.getPathParameters().get("nickname")+":"+socketMsg.getMsg());}else{//發送給發送者.fromSession.getAsyncRemote().sendText("系統消息:對方不在線或者您輸入的頻道號不對");}}else{//群發消息broadcast(nickname+": "+socketMsg.getMsg());}} catch (Exception e) {e.printStackTrace();}}/*** 發生錯誤時調用*/@OnErrorpublic void onError(Session session, Throwable error) {System.out.println("發生錯誤");error.printStackTrace();}/*** 群發自定義消息*/public void broadcast(String message) {for (WebSocketService item : webSocketSet) {/*** 同步異步說明參考:http://blog.csdn.net/who_is_xiaoming/article/details/53287691** this.session.getBasicRemote().sendText(message);**/item.session.getAsyncRemote().sendText(message);}} }resources.templates下index.html代碼,調用websocket服務
<body> <header><meta http-equiv="Content-Type" charset="utf-8"> </header> <div><input type="text" id="nickname"/><button onclick="connectWebSocket()">連接WebStock</button><button onclick="closeWebSocket()">斷開連接</button><hr/><br/>消息:<input id="text" type="text"/>頻道號:<input id="toUser" type="text"/><button onclick="send()">發送消息</button><div id="message"></div> </div> <script type="text/javascript">var websocket = null;function connectWebSocket() {var nickname = document.getElementById("nickname").value;if (nickname === "") {alert("請輸入昵稱");return;}//判斷當前瀏覽器是否支持WebSocketif ('WebSocket' in window) {websocket = new WebSocket("ws://localhost:8080/websocket/" + nickname);} else {alert('Not support websocket')}//連接發生錯誤的回調方法websocket.onerror = function () {setMessageInnerHTML("error");};//連接成功建立的回調方法websocket.onopen = function (event) {console.log(event)setMessageInnerHTML("Loc MSG: 成功建立連接");}//接收到消息的回調方法websocket.onmessage = function (event) {console.log(event)setMessageInnerHTML(event.data);}//連接關閉的回調方法websocket.onclose = function (event) {console.log(event)setMessageInnerHTML("Loc MSG:關閉連接");}//監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。window.onbeforeunload = function () {websocket.close();}}//將消息顯示在網頁上function setMessageInnerHTML(innerHTML) {document.getElementById('message').innerHTML += innerHTML + '<br/>';}//關閉連接function closeWebSocket() {websocket.close();}//發送消息function send() {//獲取輸入的文本信息進行發送var message = document.getElementById('text').value;var toUser = document.getElementById('toUser').value;var socketMsg = {msg: message, toUser: toUser};if (toUser == '') {//群聊.socketMsg.type = 0;} else {//單聊.socketMsg.type = 1;}websocket.send(JSON.stringify(socketMsg));} </script> </body>config配置文件
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @authoer:majinzhong* @Date: 2022/11/7* @description:*/ @Configuration public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();} }總結
以上是生活随笔為你收集整理的java实现聊天室(websocket)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 混淆矩阵的计算方式
- 下一篇: 美学原理-杨宁课堂笔记