SSM+Websocket实现微信网页版仿写

聊天思路

在一个窗口发送消息,确保其他建立了连接的窗口能够接收到这个消息。
1.和好友聊天:提供sendUid和receiveUid,对当前登录用户id判断是否和该receiveUid一致。
2.和群聊聊天,提供sendUid和reveiveGroupId,对当前登录用户id判断是否在该群聊中。

WebSocket部分

这里的代码差不多是整个项目中最核心的了,参考的how2j上的教程websokcet系列教程

一.后端WebSocket

Chat类

通过该类接收客户端的数据,发送数据给客户端

package cn.itcast.webSocket;


import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint("/ws/chat")
public class Chat {
    // (解决多个连接,只有1个连接消息有效的问题)
    boolean flag;
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    // 客户端发送过来的消息
    private String message;
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @OnOpen
    public void onOpen(Session session){
        this.session = session;
        ServerManger.add(this);

    }
    // 发给客户端的消息
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    @OnClose
    public void onClose(){
        ServerManger.remove(this);
        //System.out.println("关闭连接");
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("来自客户端的消息:" + message);
        flag=true;
        this.message=message;
    }

    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("发生错误");
        error.printStackTrace();
    }
}

ServerManager类

这个类就是浏览器发起一个连接请求就会创建一个Chat对象,将这些对象添加到线程安全的集合servers中。

package cn.itcast.webSocket;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

public class ServerManager {
    private static Collection<Chat> servers = Collections.synchronizedCollection(new ArrayList<Chat>());
    public static void add(Chat chat){
        servers.add(chat);
        //System.out.println("有连接加入! 当前总连接数是:"+ servers.size());
    }
    public static void remove(Chat server){

        servers.remove(server);
       // System.out.println("有连接退出! 当前总连接数是:"+ servers.size());
    }
    public static void broadcast(String msg){
        for (Chat chat : servers) {
            try {
                    chat.sendMessage(msg);
            } catch (IOException e) {
            }
        }
    }
    public static Collection<Chat> getServers(){
        return servers;
    }
}

Send

这个类会处理客户端发送过来的数据,需要确保广播(broadcast方法)最后过来的,run方法会一直运行,客户端没有新消息过来的话,也就不需要再发送消息给全部的客户端。

package cn.itcast.webSocket;

import javax.servlet.ServletConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.util.Random;


@WebServlet(name="Send",urlPatterns = "/Send",loadOnStartup=1) //标记为Servlet不是为了其被访问,而是为了便于伴随Tomcat一起启动
public class Send extends HttpServlet implements Runnable {

    public void init(ServletConfig config){
        startup();
    }

    public  void startup(){
        new Thread(this).start();
    }
    @Override
    public void run() {

        while(true) {
            // 广播当前连接数目
           // ServerManger.broadcast("{number:"+ServerManger.getServers().size()+"}");
        int duration = new Random().nextInt(1000);
        try {
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            String msg=" ";
        // 广播最后输入的,保证对每个客户端的信息都是一致的,不能在broadcast内部传入各自的信息
            for(Chat chat: ServerManager.getServers()){
                //判断chat的消息是否有值,不然每次建立新连接,就重置为null了
                if(chat.getMessage()!=null&&chat.flag==true)
                    msg=chat.getMessage();
                chat.flag=false; // 新增标志位,每次发消息过来设置为true
//                System.out.println("客户端消息:"+msg);
//                System.out.println("结束");
            }
            MyMessage my=MyMessage.getInstance();
            // 如果没有新消息发送过来,就不要发送了
            if(my.getMessage()==msg)
                msg="";
            if(msg!="") {
//                System.out.println("临时保存消息:"+my.getMessage());
//                System.out.println("发送消息:"+msg);
                my.setMessage(msg);
                // 确认发送消息,更新message
                ServerManager.broadcast(msg);
            }

        }
    }
    }

MyMessage类

保存最后从客户端发送过来的数据

package cn.itcast.webSocket;



public class MyMessage {
    private String message;
    private MyMessage(){

    }
    private static MyMessage myMessage=new MyMessage();
    public static MyMessage getInstance(){
        return myMessage;
    }
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

二.前端WebSocket

js代码

// 创建WebSocket连接
    var local="ws://localhost:8888/ws/chat";
    var web="ws://101.201.124.20:8080/ws/chat";
    var sockeet=new WebSocket(local);
    // 连接
    sockeet.onopen=function () {
    }
    // 发生错误
    sockeet.onerror=function () {

    }
    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }
    //关闭WebSocket连接
    function closeWebSocket() {
        sockeet.close();
    }
    // 客户端接收浏览器的消息(用null判断空)
    sockeet.onmessage=function (result) {
    }
    var msg={"time":time,"name":name,"value":value,"sendUid":sendUid,"receiveUid":receiveUid,"headImg":headImg};
    sockeet.send(JSON.stringify(msg));

主要页面展示

1.注册登录页面

仿写的知乎前端,那个短信验证码想做真实的,但后面想起来的时候没时间去弄了。
在这里插入图片描述

2.和好友聊天

在这里插入图片描述

3.群聊

在这里插入图片描述

4.添加好友

仿写的qq添加好友

在这里插入图片描述
在这里插入图片描述

5.群聊管理

也是仿写的qq群聊管理页面
在这里插入图片描述

6.更换头像(用户和群聊)

在这里插入图片描述

7.查看好友个人信息

在这里插入图片描述

源码下载:

github

无法访问github

找到hosts文件(C:\Windows\System32\drivers\etc下)
最后一行添加:140.82.112.3 github.com
不行的话可以换个能用的ip,我反正就这样弄的。出现提示私密链接,就注释掉github
或者直接翻墙?

项目地址

http://101.201.124.20:8080/

总结

  这个项目是去年12月开始写的,那个时候刚学完SSM框架没多久,了解到WebSocket协议之后就想着看能不能自己动手写一个网页版的聊天系统出来。
  算是自己的第一个独立思考完成的项目了,还有很多待完善之处,用的技术也比较老了,没有用流行的SpringBoot框架,自己还没学到。还有前端页面用的是jsp,其实我用起来和用html差别不大,应该要用html的。前端就是html,css,JavaScript最原生的东西,页面切换这里做的有点差,前端基本没用到多少框架的东西,都是看着知乎登录页面和微信客户端页面还有QQ那些添加好友和群聊管理页面一行一行代码敲出来的。
  一直想加上发送文件,图片的功能,我想的是在消息类再加个字段判断消息类型,还有聊天窗口里的时间提示,但是现在已经在准备考研了,就没时间去弄了,微信客户端的功能我感觉还是比较多的,所以就只把一些最核心的功能实现了。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值