基于WebSocket的聊天功能的实现(寝室圈)2.0

开发环境:eclipse+JDK7.0+Tomcat8

语言:Java

 

 

 

服务器端:

package com.lts.chat;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

//import com.opensymphony.xwork2.ActionSupport;

import net.sf.json.JSONObject;

/** @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
  * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
*/
@ServerEndpoint("/websocket")
public class ChatServer {

    private static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static Vector<Session> room = new Vector<Session>();

    /**
     *
     * 
     * @param session
     *        
     */
    
    @OnOpen
    public void onOpen(Session session) {
        room.addElement(session);
        System.out.println("客户端连接成功");
    }

    /**
     * 
     * 
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {

        // 要发送的消息保存在JSON中
        JSONObject obj = JSONObject.fromObject(message);
        //
        obj.put("date", df.format(new Date()));
        //
        for (Session se : room) {
            // 
            obj.put("isSelf", se.equals(session));
    /* getAsyncRemote()和getBasicRemote()都是WebSocket Session发送文本信息的
   方法,它们是异步与同步的区别,由于getBasicRemote()是阻塞式的,因此大部分情况下,
   推荐使用getAsyncRemote()*/    
            se.getAsyncRemote().sendText(obj.toString());
        }
        System.out.println("信息发送成功");
    }

    /**
     * 
     * 
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        room.remove(session);
    System.out.println("关闭连接");
    }

    /**
     * 
     * 
     * @param t
     */
    @OnError
    public void onError(Throwable t) {
        System.out.println("连接失败");
    }
    
    
}

客户端:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta charset="UTF-8">
  <title>寝室圈</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport"
        content="width=device-width, initial-scale=1">
  <meta name="format-detection" content="telephone=no">
  <meta name="renderer" content="webkit">
  <meta http-equiv="Cache-Control" content="no-siteapp"/>
  <link rel="alternate icon" type="image/png" href="assets/i/favicon.png">
  <link rel="stylesheet" href="assets/css/amazeui.min.css"/>
  
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/amazeui.min.js"></script>
<!-- UM相关资源 -->
<link href="assets/umeditor/themes/default/css/umeditor.css" type="text/css" rel="stylesheet">
<script type="text/javascript" charset="utf-8" src="assets/umeditor/umeditor.config.js"></script>
<script type="text/javascript" charset="utf-8" src="assets/umeditor/umeditor.min.js"></script>
<script type="text/javascript" src="assets/umeditor/lang/zh-cn/zh-cn.js"></script>
</head>
<body>
<header class="am-topbar am-topbar-fixed-top">
      <div class="am-container">
        <h1 class="am-topbar-brand">
          <a href="#">寝室圈</a>
        </h1>
        <div class="am-collapse am-topbar-collapse" id="collapse-head">
          <ul class="am-nav am-nav-pills am-topbar-nav">
            <li class="am-active"><a href="#">聊天</a></li>
            <li><a href="FriendList.jsp">退出</a></li>
          </ul>
    
          <div class="am-topbar-right">
            <button class="am-btn am-btn-secondary am-topbar-btn am-btn-sm"><span class="am-icon-pencil"></span> 动态</button>
          </div>
    
          <div class="am-topbar-right">
            <button class="am-btn am-btn-primary am-topbar-btn am-btn-sm"><span class="am-icon-user"></span> 首页</button>
          </div>
        </div>
      </div>
    </header>
    
    <div id="main">
        <!-- 聊天内容展示区域 -->
    <div id="ChatBox" class="am-g am-g-fixed" >
      <div class="am-u-lg-12" style="height:400px;border:1px solid #999;overflow-y:scroll;">
        <ul id="chatContent" class="am-comments-list am-comments-list-flip">
            <li id="msgtmp" class="am-comment" style="display:none;">
                <a href="">
                    <img class="am-comment-avatar" src="assets/images/lts.jpg" alt=""/>
                </a>
                <div class="am-comment-main" >
                    <header class="am-comment-hd">
                        <div class="am-comment-meta">
                          <a ff="nickname" href="#link-to-user" class="am-comment-author">帝国攻城狮</a>
                          <time ff="msgdate" datetime="" title="">2017-5-22</time>
                        </div>
                    </header>
                 <div ff="content" class="am-comment-bd">此处是消息内容</div>
                </div>
            </li>
        </ul>
      </div>
    </div>
    <!-- 聊天内容发送区域 -->
    <div id="EditBox" class="am-g am-g-fixed">
    <!--style给定宽度可以影响编辑器的最终宽度-->
    <script type="text/plain" id="myEditor" style="width:100%;height:140px;"></script>
    <button id="send" type="button" style="width:60px;"class="am-btn am-btn-primary am-btn-block">发送</button>
    </div>
  
</div>
<script type="text/javascript">

$(function(){


    //实例化编辑器
    var um = UM.getEditor('myEditor',{
        initialContent:" ",
        autoHeightEnabled:false,
        toolbar:[
            'source | undo redo | bold italic underline strikethrough | superscript subscript | forecolor backcolor | removeformat |',
            'insertorderedlist insertunorderedlist | selectall cleardoc paragraph | fontfamily fontsize' ,
            '| justifyleft justifycenter justifyright justifyjustify |',
            'link unlink | emotion image video  | map'
        ]
    });
    
    
    var nickname = "道长"+Math.random();
    var socket = new WebSocket("ws://${pageContext.request.getServerName()}:${pageContext.request.getServerPort()}${pageContext.request.contextPath}/websocket");
    //接收服务器的消息
    socket.onmessage=function(ev){
        var obj = eval(   '('+ev.data+')'   );
        addMessage(obj);
    }
    
    $("#send").click(function(){
        if (!um.hasContents()) {  // 判断消息输入框是否为空
            // 消息输入框获取焦点
            um.focus();
            // 添加抖动效果
            $('.edui-container').addClass('am-animation-shake');
            setTimeout("$('.edui-container').removeClass('am-animation-shake')", 1000);
        } else {
            //获取输入框的内容
            var txt = um.getContent();
            //构建一个标准格式的JSON对象
            var obj = JSON.stringify({
                nickname:nickname,
                content:txt
            });
            // 发送消息
            socket.send(obj);
            // 清空消息输入框
            um.setContent('');
            // 消息输入框获取焦点
            um.focus();
        }
    
    });
    
});

//人名nickname,时间date,是否自己isSelf,内容content
function addMessage(msg){

    var box = $("#msgtmp").clone();     //复制一份模板,取名为box
    box.show();                            //设置box状态为显示
    box.appendTo("#chatContent");        //把box追加到聊天面板中
    box.find('[ff="nickname"]').html(msg.nickname); //在box中设置昵称
    box.find('[ff="msgdate"]').html(msg.date);         //在box中设置时间
    box.find('[ff="content"]').html(msg.content);     //在box中设置内容
    box.addClass(msg.isSelf? 'am-comment-flip':'');    //右侧显示
    box.addClass(msg.isSelf? 'am-comment-warning':'am-comment-success');//颜色
    box.css((msg.isSelf? 'margin-left':'margin-right'),"20%");//外边距
    
    $("#ChatBox div:eq(0)").scrollTop(999999);     //滚动条移动至最底部
    
}


</script>

</body>
</html>

聊天页面:

posted @ 2017-06-15 16:28  帝国攻城狮  阅读(217)  评论(0编辑  收藏  举报