类似QQ的聊天工程

首先建立一个html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>far</title>
    <style>
        #chatWindow{
            font-family: 微软雅黑;
            height:700px;
            width:800px;
            font-size:12px;/*字体大小*/
            position: absolute;/*绝对定位*/
            /*margin:auto;自动布局,容器居中*/
            /*阴影效果*/
            box-shadow: gray 0px 4px 5px;/*阴影:颜色*/

            display: none;/*开始不显示chatWindow这个div*/
        }
        #title{
            height:40px;
            line-height:40px;
            /**/
            /*背景渐变*/
            background:-webkit-linear-gradient(left, #4B8CFE 0%,#ffffff 120%);
            text-align: center;/*容器中的内容居中*/
            color:white;/*字体颜色*/
        }
        #data{
            height:400px;
            border-top:1px solid gray;
            border-bottom:1px solid gray;
            overflow-y:auto;/*溢出部分显示滚动条*/
            padding: 2px;
        }
        #util>a{
            display: inline-block;
            width: 30px;
            height: 25px;
            margin: 0 5px;
        }
        #util>a:hover{
            background-color: gray;
            border-radius: 4px;
        }
        #send{
            height:180px;
            padding: 5px;/*上下左右都和输入内容有点(5px)距离*/
            outline: none;/*去掉边框*/
            overflow-y:auto;/*溢出部分显示滚动条*/
        }
        #btns{
            text-align: right;
            padding-right: 10px;/*盒子的内容距离边框的距离,简称内距离*/
        }
        .btnSetting{/* .代表class*/
            width:72px;
            height:28px;
            display: inline-block;/*转成行块标签*/
            line-height: 28px;
            border:1px solid gray;
            font-size:12px;font-family:"微软雅黑";text-align: center;
            border-radius: 3px;/*圆角*/
            text-decoration: none;/*去除下划线*/
            margin-right:10px;/*外间距,盒子与别的盒子的距离*/
            vertical-align: 1px;/*垂直位置上的调整*/
        }
        .i1{
            background:url("/images/1.jpg") no-repeat center;
        }
        .i2{
            background: url("/images/2.jpg") no-repeat center;
        }
        .i3{
            background: url("/images/3.jpg") no-repeat center;
        }
        .dataBox{
            border-radius: 5px;
            padding: 3px;
            background-color: #66afe9;
            color:black;
            width:auto;/*内容不固定大小,多少内容就用多少空间,可换行*/
            display: inline-block;
            margin-left: 10px;
        }
        .fright{
            float:right;
            clear: both;
            text-align: right;
        }
        .fleft{
            float:left;
            clear: both;
        }
        .dou{
            clear:both;
            text-align: center;
            line-height: 30px;
            border-radius: 5px;
            background-color: #4B8CFE;
        }
        #closeBtn {
            color: black; /*字体颜色*/
        }
        #closeBtn:hover{
            background-color: #EFEFF0;
        }
        #sendBtn {
            background-color: #4B8CFE;
            color:white;/*字体颜色*/
        }
        #sendBtn:hover{
            background-color: #47C8F8;
        }
    </style>
    <link rel="stylesheet" href="/css/facebox.css">
    <script src="js/jquery-2.1.1.min.js"></script>
    <script src="js/jquery.qqFace.js"></script>
    <script>
        var ws;
        //#:找到id为chatBtn的节点,绑定一个点击事件 $符号代表框架。
        $(document).ready(function () {
        $("#chatBtn").click(function () {
            //找到nickName获取val值。
            var nickName = $("#nickName").val();
            if ($.trim(nickName) == "") {//trim()函数的作用是去掉左右两边的空格。
                alert("请输入昵称!");
                return;//结束该函数
            }
            var url = "ws://" + window.location.hostname + ":8080/chatHandle/" + nickName;
            //var url1="ws://"+window.location.hostname+":8080/chatHandle/"+fang;
            //document.write(url+url1);
            ws = new WebSocket(url);
            //当后台服务器发了消息的时候,获取到后台消息
            ws.onmessage=function (chatBtn) {
                var index=chatBtn.data.indexOf("");
                if(index>=0) {
                    dou();
                }
                $("#data").scrollTop(520);
                $("#data").append(chatBtn.data+"<br>");
            }
            $("#join").hide();
            $("#chatWindow").show();
            /*
            关闭按钮
            */
            $("#closeBtn").click(function () {
                ws.close();//关闭客户端与服务端的连接
                $("#join").show();
                $("#chatWindow").hide();
            })
            /*
            发送按钮
            */
            $("#sendBtn").click(function () {
                var val=$("#send").html();
                //清空
                $("#send").html("");
                //聚焦
                $("#send").focus();
                //获取并发送
                ws.send(val);
            })
            //添加快捷键
            $("#send").keydown(function (event) {
                if(event.altKey && event.keyCode==67){
                    $("#closeBtn").click();//模拟手动点击,代码点击;
                }
                if((event.altKey && event.keyCode==83)|| event.keyCode==13){
                    $("#sendBtn").click();//模拟手动点击发送按钮,代码点击;
                }
            })
        })
            var reader=new FileReader();
            var myFile=document.getElementById("myFile");
            myFile.onchange=function () {
                var chooseFile=myFile.files[0];
                reader.readAsDataURL(chooseFile);
            }
            reader.onload=function () {
                var obj=document.createElement("img");
                obj.src=reader.result;
                $("#send").append(obj);
            }
            $("#myFile").hide();
            $(".i1").click(function () {
                $("#myFile").click();
            })
            $(".i2").qqFace({
                id:'facebox',
                assign:'send',
                path:'arclist/'
            })
            /*拖拽部分*/
            var title=document.getElementById("title");
            var pyx,pyy;
            title.ondragstart=function (e) {
                pyx=e.offsetX;
                pyy=e.offsetY;
            }
            title.ondrag=function (e) {
                var x=e.pageX;
                var y=e.pageY;
                if(x==0&&y==0)   return;
                $("#chatWindow").css("left",x-pyx);
                $("#chatWindow").css("top",y-pyy);
            }
            $(".i3").click(function () {
                ws.send("");
            })
            function dou() {
                var initx=$("#chatWindow").offset().left;
                var inity=$("#chatWindow").offset().top;
                for(var i=0;i<=10;i++){
                    $("#chatWindow").animate({"left":initx-10,"top":inity-10},10);
                    $("#chatWindow").animate({"left":initx,"top":inity},10);
                    $("#chatWindow").animate({"left":initx+10,"top":inity+10},10);
                    $("#chatWindow").animate({"left":initx,"top":inity},10);
                }
            }
        })
    </script>
</head>
<body>
<div id="join"><!-----div可以看成一个盒子,容器。固定页面布局。CSS(放head里面)相当对html的"化妆";------->
    <input id="nickName" type="text"><br>
    <input id="chatBtn" type="button" value="加入聊天室"><br>
</div>
<div id="chatWindow">
    <div id="title" draggable="true">far away</div>
    <div id="data"></div><!----聊天内容------->
    <div id="util"><!--工具区域-->
    <input type="file" id="myFile">
    <a class="i1" href="javascript:;"></a>
    <a class="i2" href="javascript:;"></a>
    <a class="i3" href="javascript:;"></a>
</div>
    <div id="send" contenteditable="true"></div><!----要发送内容------->
    <div id="btns"><!------发送和关闭按钮-------->
        <a id="closeBtn" class="btnSetting" href="javascript:;">关闭(<u>C</u>)</a>
        <a id="sendBtn" class="btnSetting" href="javascript:;">发送(<u>S</u>)</a>
    </div>
</div>
</body>
</html>

后台控制代码:
package com.seecon.Chat.handle;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.PathParam;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

@ServerEndpoint("/chatHandle/{nickName}")
public class ChatHandle {
    //创建一个静态的“袋子”(跟对象无关),用来装所有的session,也就是所有用户的会话;
    private static List<Session> users=new ArrayList<Session>();//static可以共享。
    public static synchronized void add(Session session){//静态方法不依赖对象
        users.add(session);
    }
    public synchronized  static void remove(Session session){
        users.remove(session);
    }
    private void sendAll(String message){
        for (Session user : users) {
            user.getAsyncRemote().sendText(message);
        }
    }
    private String nickName;/*当前会话的昵称*/
    @OnOpen
    public void connect(Session session,@PathParam("nickName") String nickName) throws Exception {
        System.out.println(nickName + "连接上了后台服务器程序" + session);
        add(session);
        sendAll("<div class='fleft'>-----欢迎[" + nickName + "]------加入聊天室  "+"当前聊天室人数:"+users.size()+"</div>");
        this.nickName=nickName;
    }
    @OnClose
    public void exit(Session session,@PathParam("nickName") String nickName) throws Exception{
        remove(session);
        sendAll("<div class='fright'>----[" + nickName + "]------退出聊天室"+"当前聊天室人数:"+users.size()+"</div>");
    }
    @OnMessage
    public void receiveMessage(Session session,String message) throws Exception{
        Calendar c=Calendar.getInstance();
        int hour=c.get(Calendar.HOUR_OF_DAY);
        String hourStr=hour>=10?hour+"":"0"+hour;
        int minute=c.get(Calendar.MINUTE);
        String minuteStr=minute>=10?minute+"":"0"+minute;
        int second=c.get(Calendar.SECOND);
        String secondStr=second>=10?second+"":"0"+second;
        String fullTime=hourStr+":"+minuteStr+":"+secondStr;
        //构建message
        if(message.equals("")){
            message="<div class='dou'>"+nickName+"给您发送了一个窗口抖动</div>";
            String str="&nbsp;&nbsp;"+fullTime+"<br>"+message;
            sendAll(""+str);
        }else {
            message = "<div class='dataBox'>" + message + "</div>";
            String str = nickName + "&nbsp&nbsp" + fullTime + "<br>" + message;
            sendAllMessage(str, session);
        }
    }
    private void sendAllMessage(String message,Session session){
        //把Message的数据通知给所有会话
        for(Session user:users){
            if(user==session){
                user.getAsyncRemote().sendText("<div class='fright'>"+message+"</div>");
            }
            else{
                user.getAsyncRemote().sendText("<div class='fleft'>"+message+"</div>");

            }
        }
    }

}
原文地址:https://www.cnblogs.com/xm970829/p/9093043.html