目录
1.项目展示
2.知识要点
3.用户列表
具体功能:
进入聊天室之前,需要先输入用户名再进入,聊天室中可以进行群聊,或者点击用户列表左边的CheckBox来制定给某些人发信息,或者一个人实现单聊。每个用户进入时会显示“欢迎**进入聊天室”,离开会显示“恭送**离开聊天室”
项目在我上一篇博文中的项目中进行改进:https://blog.csdn.net/Doctor_LY/article/details/81362718
在上一篇博文的技术上进行改进,我查看了一些资料,补充了一些知识点,然后再对这个项目进行开发。
整体的思路还是比较简单,上一个项目其实已经实现了群聊,在基础上,我们只需要添加的功能是:
多聊和单聊就是判断你选择了那个用户,获取该用户的SessionID,然后在广播的时候
根据已经获取的ID,来选择发送给那些用户。
在登录界面点击提交时,我们需要获取用户输入的用户名。然后传到聊天室界面,聊天室的页面js会访问服务器的WebSocket,此时我们需要把传过去的用户名,一起插到访问WebSocket服务器的URL中。WebScoket服务器再获取这个用户名,用来做用户列表。
登陆页面HTML:
WebSocket
提交的方法和登陆的方法:
package com.example.websocket.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
@Controller
public class LoginController {
@PostMapping("/LoginController")
public ModelAndView login(@RequestParam("username") String username,
Map map){
map.put("username",username);
return new ModelAndView("chat",map);
}
@GetMapping("/login")
public ModelAndView client(){
return new ModelAndView("login");
}
}
可以看到login方法获取用户名参数后,转到chat页面,因为这里用的是FreeMarker模板引擎,在chat页面中只需要用${username},就可以获取到用户名。chat页面中的js会去访问Websocket,需要携带参数过去。
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
webSocket = new WebSocket('ws://localhost:8080/webSocket?username=' + '${username}');
} else {
alert("当前浏览器不支持WebSocket");
}
然后WebSocket需要获取该参数:
@OnOpen
public void onOpen(Session session){
this.session=session;
webSockets.add(this);
//获取用户名
String s=session.getQueryString();
String urlUsername=s.split("=")[1];
try {
username=URLDecoder.decode(urlUsername,"UTF-8");
}
catch (Exception e){
e.printStackTrace();
}
//把SessionID和用户名放进集合里面
map.put(session.getId(),username);
System.out.println("有新的连接,总数"+webSockets.size()+"sessionId:"+session.getId()+" "+username);
String content="欢迎"+username+"进入聊天室!";
Message message=new Message(content,map);
send(message.toJson());
}
private Session session;
private String username;
private static CopyOnWriteArraySet webSockets=new CopyOnWriteArraySet<>();
private static Map map=new HashMap<>();
因为在每一个WebSocket对象中,我们添加了两个属性,一个username一个session,所以对应每一个通道它都有自己的session和username。我们定义一个Map集合来存储session和username,这也方便后期用户离开聊天室去掉该用户。用户访问WebScoket,握手成功后会触发OnOpen方法,这时候我们就要广播说,某某同学进入聊天室了。所以就要在OnOpen方法中,广播了。
在上一个项目中,我们广播信息是直接用字符串来表示信息,在这个项目中,其实也是用字符串,但是是一个JSON字符串,这样方便携带更多信息,而且规范。我们想一下要广播的信息包括哪些内容,1、欢迎**进入聊天室。2、还要一个用户列表,用来及时更新用户列表
定义一个广播信息类:
package com.example.websocket.vo;
import com.google.gson.Gson;
import java.text.DateFormat;
import java.util.Date;
import java.util.Map;
public class Message {
private String content;
private Map names;
private Date date=new Date();
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public void setContent(String name,String msg) {
this.content = name+" "+DateFormat.getDateTimeInstance().format(date) +":
"+msg;
}
public Map getNames() {
return names;
}
public void setNames(Map names) {
this.names = names;
}
public String toJson(){
return gson.toJson(this);
}
private static Gson gson=new Gson();
public Message(String content, Map names) {
this.content = content;
this.names = names;
}
public Message() {
}
}
public void setContent(String name,String msg) {
this.content = name+" "+DateFormat.getDateTimeInstance().format(date) +":
"+msg;
}
上面这个方法是用来拼装规范信息的,每一条信息会说明是谁发送过来和具体的时间。
一个对象要转成JSON字符串就需要用到Gson。在Maven添加相关的依赖。
com.google.code.gson
gson
2.8.5
把信息拼装到Message对象中,然后转成JSON字符串,就可以广播了。
客户端在websocket.onmessage方法中接收到字符串和解析JSON字符串
webSocket.onmessage = function (event) {
$("#userList").html("");
eval("var msg=" + event.data + ";");
if (undefined != msg.content)
setMessageInnerHTML(msg.content);
if (undefined != msg.names) {
$.each(msg.names, function (key, value) {
var htmlstr = ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''
+ ''+value+''
+ ''
+ ' '
$("#userList").append(htmlstr);
})
}
}
把用户列表解析出来就得到用户列表了。