websocket聊天平台(初版)

介绍

websocket我这文章就不介绍了,具体意思百度查下,很简单。
我就一句话介绍下,实时通信的!

项目

我把我这个简易版聊天平台源码开源发在这篇文章里面。
用法,以及每个模块的功能都说尽量的说详细点。

源码

maven

<dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>    <!-- 就是这句 -->
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <scope>compile</scope>
        </dependency>

Java代码

import net.sf.json.JSONObject;
import sun.security.krb5.internal.HostAddress;
import sun.security.rsa.RSASignature;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@ServerEndpoint("/websock/{name}")
public class WebSocket {
    //name用于记录当前的websoket是谁
    private  String name;
    //链接,用于记录当前的链接
    private Session session;

    private  static Map<String,WebSocket> AllClients= new HashMap<>();
    public  static List<String> haoyou=new ArrayList<>();

    //打开链接
    @OnOpen
    public void onOpen(@PathParam("name") String name, Session session){
        this.name=name;
        this.session=session;
        AllClients.put(name,this);
        System.out.println("建立链接");
        haoyou.add(name);


    }

    //处理消息
    @OnMessage
    public void OnMessage(Session session,String message){
        JSONObject jsonobject=JSONObject.fromObject(message);
        int  flag= Integer.parseInt(jsonobject.getString("flag"));
        int  Radiovalue= Integer.parseInt(jsonobject.getString("Radiovalue"));
        System.out.println("flag="+flag+"Radiovalue="+Radiovalue);
        if(flag==0&&Radiovalue==88888){
            //好友上线功能
            HaoYou(session,message);
        }else if(flag==1&&Radiovalue!=88888){
            if(Radiovalue==1){
                //发消息模块(私聊)
                SendXiaoXi(session,message);
            }else {
                //群发消息
                SendXiaoXiAll(session,message);
            }
        }
        else{
            System.out.println("未知识别码");
        }



    }

    public void SendXiaoXiAll(Session session,String message){
        System.out.println("当前为群聊模式");
        JSONObject jsonobject=JSONObject.fromObject(message);
        String toMessage= jsonobject.getString("toMessage");
        String username=jsonobject.getString("username");
        //原理找到每个用户的名字
        //WebSocket socket=AllClients.get(to);
        //Session tosession=socket.getSession();
        WebSocket socket=null;
        Session tosession=null;
        System.out.println("当前在线好友"+haoyou.size());
        for(int i = 0 ; i < haoyou.size() ; i++) {
            //System.out.println(haoyou.get(i));
           if(!haoyou.get(i).equals(username)){
               socket=AllClients.get(haoyou.get(i));
               tosession=socket.getSession();
               if(tosession.isOpen()){
                   tosession.getAsyncRemote().sendText(username+"群发了一个为消息:"+toMessage);
                   session.getAsyncRemote().sendText("给群发消息:"+toMessage);
               }
           }

        }

    }




    public void HaoYou(Session session,String message){
        JSONObject jsonobject=JSONObject.fromObject(message);
        //当前用户的名字(需要排除当前名字)
        String username=jsonobject.getString("username");
        System.out.println("当前在线-->"+username);
        System.out.println("当前在线人数"+ haoyou.size());
        String str_haoyou="";
        if(haoyou.size()==1){
            session.getAsyncRemote().sendText("当前无人在线,欢迎使用");
        }else{
            for(int i = 0 ; i < haoyou.size() ; i++) {
                //System.out.println(haoyou.get(i));
                if(!haoyou.get(i).equals(username)){
                    str_haoyou=str_haoyou+haoyou.get(i)+" ";
                }
            }
            System.out.println("好友上线列表为"+str_haoyou);
            session.getAsyncRemote().sendText("当前你的好友"+str_haoyou+"在线");
        }

    }
    public void SendXiaoXi(Session session,String message){
        System.out.println("当前为私聊模式");
        JSONObject jsonobject=JSONObject.fromObject(message);
        String to=jsonobject.getString("toUer");
        String toMessage= jsonobject.getString("toMessage");
        //目标接收者的wevsocket
        WebSocket socket=AllClients.get(to);
        //通过session发送消息
        if(socket!=null){
            Session tosession=socket.getSession();
            if(tosession.isOpen()){
                //找到链接的另外一端
                String username= jsonobject.getString("username");
                tosession.getAsyncRemote().sendText(username+"给你发消息:"+toMessage);
                session.getAsyncRemote().sendText("给"+to+"发消息:"+toMessage);
            }
        }else{
            //正常来说要缓存消息
            session.getAsyncRemote().sendText("对方不在线");
        }
    }


    @OnError
    public void OnError(Session session,Throwable e){

    }

    @OnClose
    public void OnClose(Session session){

    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    public static Map<String, WebSocket> getAllClients() {
        return AllClients;
    }

    public static void setAllClients(Map<String, WebSocket> allClients) {
        AllClients = allClients;
    }
}

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>好友聊天 1.0</title>
    <script type="text/javascript">
        var websocket=null;
        var Radiovalue=1;
        function connection(){
            var username=document.getElementById("username").value;
            if("WebSocket" in window){
                //当前浏览器支持不支持websoket
                websocket=new WebSocket("ws://"+document.location.host+"/websock/"+username);
            }else{
                alert("什么破电脑");
            }
            websocket.onopen=function (){
                console.log("username--->"+username);
                document.getElementById("message").innerHTML="建立链接了";

                var message='{"toUer":"'+""+'","toMessage":"'+""+'","username":"'+username+'","flag":"'+0+'","Radiovalue":"'+88888+'"}';
                websocket.send(message);

            }

            websocket.onmessage=function (event){
                var data=event.data;
                document.getElementById("message").innerHTML=data;
            }

            websocket.onerror=function (){
                document.getElementById("message").innerHTML="出现异常了";
            }

            websocket.onclose=function (){
                document.getElementById("message").innerHTML="链接关闭了";
            }

            window.onbeforeunload=function (){
                //监听窗口的关闭
                if(webSoket!=null){
                    webSoket.close();
                }
            }
        }
        function sendMessage(){
            //获取发送给谁
            //获取发送内容
            var toUser=document.getElementById("toUser").value;
            var toMessgae=document.getElementById("toMessgae").value;
            var username=document.getElementById("username").value;
            if(websocket!=null){
                var message='{"toUer":"'+toUser+'","toMessage":"'+toMessgae+'","username":"'+username+'","flag":"'+1+'","Radiovalue":"'+Radiovalue+'"}';
                websocket.send(message);
            }
        }

        function RadioOnclick(value){
            Radiovalue=value;
            console.log("勾选为-->"+Radiovalue);
        }

    </script>
</head>
<body>
<input id="username" name="context" type="text"><button onclick="connection()">链接</button><br>
接收者名字:<input type="text" id="toUser" name="toUser"><br>
内容: <input type="text" id="toMessgae" name="toMessgae"><br>
<input type="radio" checked="true" name="storeLocation" value="1" onclick="RadioOnclick(this.value)" >私聊
<input type="radio" name="storeLocation" value="2" onclick="RadioOnclick(this.value)">群发
<input type="hidden"  id="storeLocation" value=""/>
<br><br>
<button onclick="sendMessage()">发送</button><br><br><br><br><br><br>
<span style="color: red">提示消息:</span><span id="message"> </span>
</body>
</html>

介绍

源码上面很清楚,如果maven不全,那就自行百度查下需要了自己粘贴找一个就行了。主要是我想介绍下这里面的重点。

知识重点!!

  1. 第一点我要说的很简单,你要使用这个还是去百度查下这玩意是干啥的,其实我理解为就是双向通信用的。
  2. 这个里面前端里面也有几个方法,我源码里面也写到了。onopen:用于指定连接成功后的回调函数;onmessage:用于指定当从服务器接受到信息时的回调函数;onclose:用于指定连接关闭后的回调函数;onerror:用于指定连接失败后的回调函数; 我个人感觉这几个最为重要,其他可以了解了解就欧克了
  3. 连接呢,前端new WebSocket("ws://"+document.location.host+"/websock/"+username);后端@ServerEndpoint("/websock/{name}");这样即可以,也就是意思必须保持一样的,要不然匹配不上,就会连不上。

前端

  1. 必须配置上面那个通信通道,要不然没有用的
  2. 发消息呢,也就是我源码中sendMessage()函数中,websocket.send(message);也就是用上面所提到的websocket对象调用send函数即可,如果你配置没有问题的话,此时此刻你调用了那便把数据发送到后端去了。后端接收的方法等哈下面会提到。这里利用的json格式字符串传入的,后端怎么接收我也会说到
  3. 第三点呢,算是补充,大家可以在各个方法里面增加对应的功能,可扩展类型的,比如我写了连接成功会有一个好友上线功能。你可以在用户退出增加一个好友下线功能等等。
  4. 待补充。。。。

后端介绍就有点多了
后端
  • 首先要注意就是那个通信通道是否正确,所以后端也有对应的方法,并且名字是一样的,函数可以自定义,但必须用@OnOpen这个注解。这个里面可以加上发送消息功能,这样可以测试是否成功接通
  • 处理消息:函数也是自定义,但必须使用@OnMessage这个注解,这个也就以为着,上面前端提到的发送消息,也是在这里处理的。处理json使用json的包JSONObject jsonobject=JSONObject.fromObject(message);使用这个。
  • @OnMessage函数的参数里面切记必须加上Session session,String message,一个是session一个是message,message就是前端传过来的字符串消息。
  • onOpen这个函数参数:@PathParam("name") String name, Session session,@PathParam("name") String name这个就是你登录的用户名,我这里是这样获取到的,你可以利用别的获取方法有很多种。
  • 重点介绍也就是上面这些,下来就是你发送消息的时候判断下对方的session是否存在等考虑的问题。
  • 我这里写了处理消息(私聊和群聊的模块),和好友上线功能模块提示
  • 好友上线功能

    利用OnOpen这个方法来判断那些好友上线了,我做了对应的处理。使用了一个list集合,因为只是统计用户名字,所以用list接口很简单。写法有很多种。
    功能实现过程:在连接的时候存入对应的名字到list集合,如果现在有第二人上线了,把list集合直接遍历下即可,但是切记一定要把第二人用户名除去。然后把list集合对应的结果放入到字符串里面即可,你可以也做出对应的处理。我这里没有做。
    整理好字符串利用这个session.getAsyncRemote().sendText("当前无人在线,欢迎使用");这个意思就是把此消息,返回到当前用户的页面端。也就是这个消息是本人看的。还有一个是发送到对方的,我没有在源码里面的,下面会提到。

    私聊功能

    利用OnMessage这个函数来接收消息等前端发送过来的东西。我这里先解析json字符串,然后提取到对应的用户账号和消息字符串。提取到对应的用户名字,然后去存放的map集合里面查找对应的session是否存在(肯定是存在的),我知道存在,但是必须找到对应的,因为给对方发消息,必须要用对方的session,找到之后,我还是做的看对方的session是否存活,要不然就判断对方不在线,要不然在发送,发送也相当的简单tosession.getAsyncRemote().sendText(username+"群发了一个为消息:"+toMessage);用对方的sesson发送即可。

    群聊模式

    私聊模式懂了,群聊更简单,无非就是要把在线的用户,每个session都要拿到,然后在发送。
    这里重点要说的就是,必须排除本用户,也就是那个要用要发群消息,那就把那个用户排除,然后利用剩下用户的session给他们发消息即可,代码也写到了
    群聊和私聊代码有点类似,无非就是稍微有所改动。

    总结

    这次吸收不错,这篇文章我也写了快1个消息,尽可能的希望大家都可以简单的上手,里面有很多功能没有扩展,因为我要去补作业,马上期末了,后面功能在说吧,源码上面也发了,可以自己玩玩,运行截图就不放出来了。

    评论区
    头像