WebSocket+SpringBoot聊天室(一)

目录

 

1.项目展示

2.知识要点

3.用户列表


1.项目展示

具体功能:

进入聊天室之前,需要先输入用户名再进入,聊天室中可以进行群聊,或者点击用户列表左边的CheckBox来制定给某些人发信息,或者一个人实现单聊。每个用户进入时会显示“欢迎**进入聊天室”,离开会显示“恭送**离开聊天室”

项目在我上一篇博文中的项目中进行改进:https://blog.csdn.net/Doctor_LY/article/details/81362718

2.知识要点

在上一篇博文的技术上进行改进,我查看了一些资料,补充了一些知识点,然后再对这个项目进行开发。

  • 一个WebSocket对象就是一个管道,一个管道代表一个session(上面三个客户端,其实就是有三条连接服务器的管道)
  • 管道与管道之间我是用Session来区分

整体的思路还是比较简单,上一个项目其实已经实现了群聊,在基础上,我们只需要添加的功能是:

  • 用户列表
  • 用户进入和离开提示
  • 用户单聊和多聊

多聊和单聊就是判断你选择了那个用户,获取该用户的SessionID,然后在广播的时候

根据已经获取的ID,来选择发送给那些用户。

3.用户列表

在登录界面点击提交时,我们需要获取用户输入的用户名。然后传到聊天室界面,聊天室的页面js会访问服务器的WebSocket,此时我们需要把传过去的用户名,一起插到访问WebSocket服务器的URL中。WebScoket服务器再获取这个用户名,用来做用户列表。

登陆页面HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body style="background:#f5f5f5 url('../img/bg.jpg') no-repeat center;background-size:cover;height: 600px;">
    <form method="post" action="/LoginController" style="text-align: center;margin: 200px 0 0 0">
        <h1>WebSocket聊天室</h1>
        <h2>用户名:</h2><input placeholder="请输入聊天时的用户名" type="text" name="username"
                            style="border-radius: 5px;width: 180px;height: 30px;padding-left: 10px">
        <input class="btn btn-primary" type="submit">
    </form>
</body>
</html>

提交的方法和登陆的方法:

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<String,Object> 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<WebSocket> webSockets=new CopyOnWriteArraySet<>();
private static Map<String,String> 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<String,String> 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) +":<br/> "+msg;
    }

    public Map<String, String> getNames() {
        return names;
    }
    public void setNames(Map<String, String> names) {
        this.names = names;
    }


    public String toJson(){
        return gson.toJson(this);
    }

    private static Gson gson=new Gson();

    public Message(String content, Map<String, String> names) {
        this.content = content;
        this.names = names;
    }

    public Message() {
    }
}

    public void setContent(String name,String msg) {
        this.content = name+" "+DateFormat.getDateTimeInstance().format(date) +":<br/> "+msg;
    }

上面这个方法是用来拼装规范信息的,每一条信息会说明是谁发送过来和具体的时间。

一个对象要转成JSON字符串就需要用到Gson。在Maven添加相关的依赖。

<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
     <groupId>com.google.code.gson</groupId>
     <artifactId>gson</artifactId>
     <version>2.8.5</version>
</dependency>

把信息拼装到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 = '<li>'
                        + '<div class="checkbox checkbox-success checkbox-inline">'
                        + '<input type="checkbox" class="styled" id="'+key+'" value="'+key+'" checked>'
                        + '<label for="'+key+'"></label>'
                        + '</div>'
                        + '<div class="liLeft"><img src="img/2.png"/></div>'
                        + '<div class="liRight">'
                        + '<span class="intername">'+value+'</span>'
                        + '</div>'
                        + '</li>'

                $("#userList").append(htmlstr);
            })
        }
    }

把用户列表解析出来就得到用户列表了。

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值