1、上一篇文章写了单聊和单房间群聊的实现,实际运用中当然不可能只能创建一个房间,这一篇文章就介绍多房间的实现。
2、界面展示
![$7GQ4{A5)6{{GQ}W5I%QNO.png
![THG[@N]LYO6O{3N(]N]CBAW.png](https://upload-images.jianshu.io/upload_images/14217092-b83c80670ff462fe.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![ZQ7D0}M$A4WZD8})I@01`K.png
3、代码结构
4、复制上一篇测试成功后的项目复制粘贴,修改项目名称。
WebSocketConfig代码与上一篇不变,controller代码我直接删除了,请自行按需求编写。
修改WebSocketServer代码如下:
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* writer: holien
* Time: 2017-08-01 13:00
* Intent: webSocket服务器
*/
@Slf4j
@ServerEndpoint("/webSocket/chat/{roomName}/{username}")
@Component
public class WebSocketServer {
// 使用map来收集session,key为roomName,value为同一个房间的用户集合
// concurrentMap的key不存在时报错,不是返回null
private static final Map<String, Set<Session>> rooms = new ConcurrentHashMap();
private static final Map<String, String> userNameList = new ConcurrentHashMap();
@OnOpen
public void connect(@PathParam("roomName") String roomName,@PathParam("username") String username, Session session) throws Exception {
System.out.println("连接成功");
// 将session按照房间名来存储,将各个房间的用户隔离
if (!rooms.containsKey(roomName)) {
// 创建房间不存在时,创建房间
Set<Session> room = new HashSet<Session>();
// 添加用户
room.add(session);
rooms.put(roomName, room);
} else {
// 房间已存在,直接添加用户到相应的房间
rooms.get(roomName).add(session);
}
System.err.println("username:"+username);
System.out.println("a client has connected!");
}
@OnClose
public void disConnect(@PathParam("roomName") String roomName,@PathParam("userName") String userName, Session session) {
rooms.get(roomName).remove(session);
System.out.println("a client has disconnected!");
}
@OnMessage
public void receiveMsg(@PathParam("roomName") String roomName,@PathParam("username") String username,
String msg, Session session) throws Exception {
// 此处应该有html过滤
msg = username + ":" + msg;
System.out.println(msg);
// 接收到信息后进行广播
broadcast(roomName, msg);
}
// 按照房间名进行广播
public static void broadcast(String roomName, String msg) throws Exception {
for (Session session : rooms.get(roomName)) {
System.out.println("session:"+session.getBasicRemote());
session.getBasicRemote().sendText(msg);
}
}
}
5、修改chat.html页面代码如下:
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8">
<title>网络聊天室</title>
</head>
<style type="text/css">
.talk_con {
width: 600px;
height: 510px;
border: 1px solid #666;
margin: 50px auto 0;
background: #f9f9f9;
}
.talk_show {
width: 580px;
height: 420px;
border: 1px solid #666;
background: #fff;
margin: 10px auto 0;
overflow: auto;
}
.talk_input {
width: 580px;
margin: 10px auto 0;
}
.whotalk {
width: 80px;
height: 30px;
float: left;
outline: none;
}
.talk_word {
width: 500px;
height: 26px;
padding: 0px;
float: left;
margin-left: 0px;
outline: none;
text-indent: 10px;
}
.talk_sub {
width: 56px;
height: 30px;
float: left;
margin-left: 10px;
}
.atalk {
margin: 10px;
}
.atalk span {
display: inline-block;
background: #0181cc;
border-radius: 10px;
color: #fff;
padding: 5px 10px;
}
.btalk {
margin: 10px;
text-align: right;
}
.btalk span {
display: inline-block;
background: #ef8201;
border-radius: 10px;
color: #fff;
padding: 5px 10px;
}
</style>
<style type="text/css">
.msg_board {
width: 322px;
height: 100px;
border: solid 1px darkcyan;
padding: 5px;
overflow-y: scroll;
// 文字长度大于div宽度时换行显示
word-break: break-all;
}
/*set srcoll start*/
::-webkit-scrollbar
{
width: 10px;
height: 10px;
background-color: #D6F2FD;
}
::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
/*border-radius: 5px;*/
background-color: #D6F2FD;
}
::-webkit-scrollbar-thumb
{
height: 20px;
/*border-radius: 10px;*/
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #89D7F7;
}
/*set srcoll end*/
</style>
<body>
<div class="talk_con">
<div style="margin-top: 10px">
<label>房间名</label>
<input id="input_roomName" size="10" maxlength="10">
<label>用户名</label>
<input id="username" size="10" maxlength="10">
<input type="button" value="进入聊天室" onclick="initWebSocket()" />
<input type="button" value="退出聊天室" onclick="closeWs()" /><br>
</div>
<div class="talk_show" id="words">
<!--<div class="atalk"><span id="asay">A说:吃饭了吗?</span></div>
<div class="btalk"><span id="bsay">B说:还没呢,你呢?</span></div>-->
</div>
<div class="talk_input">
<!--<select class="whotalk" id="who">
<option value="0">A说:</option>
<option value="1">B说:</option>
</select>-->
<input type="text" class="talk_word" id="input_msg">
<input type="button" value="发送" class="talk_sub" onclick="send_msg()">
</div>
</div>
<!--<div class="msg_board"></div>-->
<!--<input id=s"input_msg" size="43" maxlength="40">-->
<!--<input type="button" value="发送" onclick="send_msg()" />-->
</body>
<script type="text/javascript">
var webSocket;
function send_msg() {
if (webSocket != null) {
var input_msg = document.getElementById("input_msg").value.trim();
if (input_msg == "") {
return;
}
webSocket.send(input_msg);
// 清除input框里的信息
document.getElementById("input_msg").value = "";
} else {
alert("您已掉线,请重新进入聊天室...");
}
};
function closeWs() {
webSocket.close();
};
function initWebSocket() {
var roomName = document.getElementById("input_roomName").value;
// 房间名不能为空
if (roomName == null || roomName == "") {
alert("请输入房间名");
return;
}
var username = document.getElementById("username").value.trim();
if (username == "" || username==null) {
alert("用户名不能为空")
return;
}
if ("WebSocket" in window){
// alert("您的浏览器支持 WebSocket!");
if (webSocket == null) {
var url = "ws://localhost:8080/webSocket/chat/" + roomName+"/"+username;
// 打开一个 web socket
webSocket = new WebSocket(url);
} else {
alert("您已进入聊天室...");
}
webSocket.onopen = function () {
alert("已进入聊天室,畅聊吧...");
};
webSocket.onmessage = function (evt) {
var Words = document.getElementById("words");
//得到返回的数据
var received_msg = evt.data;
var userName = document.getElementById("username").value;
if (received_msg.split(":")[0] == userName ){
var str = '<div class="btalk"><span id="bsay">' + received_msg + '</span></div>';
} else
var str = '<div class="atalk"><span id="asay">' + received_msg + '</span></div>';
Words.innerHTML = Words.innerHTML + str;
Words.scrollTop = Words.scrollHeight;
};
webSocket.onclose = function () {
// 关闭 websocket,清空信息板
alert("连接已关闭...");
webSocket = null;
document.getElementsByClassName("msg_board")[0].innerHTML = "";
};
}
else {
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
}
</script>
</html>
5、接下来测试代码是否能运行成功。主要修改就只是server的代码处理,前端页面只是负责展示返回的消息,这次我找了个好一点的页面,css之类的代码没必要深究。重点将server的代码与上一篇的对比,看懂了就会理解websocket转发的代码逻辑。