JavaWeb網頁聊天室(WebSocket即時通信)

原文:http://baike.xsoftlab.net/view/656.htmljavascript

Git地址

http://git.oschina.net/loopcc/WebSocketChatcss

 

概要:html

WebSocket是HTML5一種新的協議,它實現了瀏覽器與服務器全雙工通訊,這裏就將使用WebSocket來開發網頁聊天室,前端框架會使用AmazeUI,後臺使用Java,編輯器使用UMEditor。前端

Java和WebSocket開發網頁即時聊天室java

11、項目說明及簡介

1. 項目簡介

WebSocket是HTML5一種新的協議,它實現了瀏覽器與服務器全雙工通訊,這裏就將使用WebSocket來開發網頁聊天室,前端框架會使用AmazeUI,後臺使用Java,編輯器使用UMEditor。jquery

2. 涉及知識點

網頁前端(HTML5 + CSS3 + JS)和 JavaEE。git

3. 軟件環境

Tomcat8web

JavaEE7json

JDK7後端

Eclipse-JavaEE 或 MyEclipse

支持HTML5的瀏覽器

4. 相關框架

jQuery—1.X

妹子UI(AmazeUI-2.5.2)

百度富文本編輯器(UMeditor1_2_2)

5. 效果預覽

 

6.Git地址

http://git.oschina.net/loopcc/WebSocketChat

 

22、新建空項目

打開Eclipse JavaEE,新建一個名爲Chat的Dynamic Web Project,而後導入處理JSON格式字符串所須要的包,

Text |  複製
1
2
3
4
5
6
commons-beanutils-1.8.0.jar
commons-collections-3.2.1.jar
commons-lang-2.5.jar
commons-logging-1.1.1.jar
ezmorph-1.0.6.jar
json-lib-2.4-jdk15.jar

把這幾個包放在/WEB-INF/lib目錄下,最後把項目發佈到Tomcat8服務器上,到此空項目就搭建完成了。

Eclipse的默認項目根目錄叫WebContent, MyEclipse默認項目根目錄叫WebRoot,

在本篇文檔中,咱們接下來用WebRoot做爲項目根目錄。

33、編寫前端頁面

這裏使用了AmazeUI框架,它是一個跨屏自適應的前端框架

消息輸入框使用了UMEditor,它是一個富文本在線編輯器,能讓咱們的消息內容多姿多彩。

在WebContent目錄下新建一個名爲index.jsp的頁面,

首先從AmazeUI官網下載壓縮包,而後解壓把assets文件夾拷貝到WebRoot目錄下,這樣咱們就能使用AmazeUI了。

再從UEditer官網下載Mini版的JSP版本壓縮包,解壓後把整個目錄拷貝到WebRoot目錄下,

接下來就能夠編寫前端代碼了,代碼以下(可按照本身的審美去編寫):

<%@ 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>Landing Page | Amaze UI Example</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"/>
    <script src="assets/js/jquery.min.js"></script>
    <!-- 妹子UI相關資源 -->
    <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/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="#">項目</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 class="am-comment am-comment-success" style="margin-right:20%;">
                <a href="">
                    <img class="am-comment-avatar" src="assets/images/other.jpg" alt=""/>
                </a>
                <div class="am-comment-main" >
                    <header class="am-comment-hd">
                        <div class="am-comment-meta">
                          <a href="#link-to-user" class="am-comment-author">某人</a>
                          <time datetime="" title="">2014-7-12 15:30</time>
                        </div>
                    </header>
                 <div class="am-comment-bd">此處是消息內容</div>
                </div>
            </li>
            <li class="am-comment am-comment-flip am-comment-warning" style="margin-left:20%;">
                <a href="">
                    <img class="am-comment-avatar" src="assets/images/xia.jpg" alt=""/>
                </a>
                <div class="am-comment-main" >
                    <header class="am-comment-hd">
                        <div class="am-comment-meta">
                          <a href="#link-to-user" class="am-comment-author">某人</a>
                          <time datetime="" title="">2014-7-12 15:30</time>
                        </div>
                    </header>
                 <div 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" class="am-btn am-btn-primary am-btn-block">發送</button>
    </div></div><script type="text/javascript">$(function(){
    //窗口大小變化時,調整顯示效果
    $("#ChatBox div:eq(0)").height($(this).height()-290);
    $(window).resize(function(){
        $("#ChatBox div:eq(0)").height($(this).height()-290);
    });
    //實例化編輯器
    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'
        ]
    });});
    </script>
</body>
</html>

編寫完成以後啓動Tomcat服務器,而後訪問index.jsp ,會看到設計好的頁面效果。

上面的實例代碼裏有兩條示例消息,一條別人的消息,一條本身的消息。

44、消息流轉

聊天室的核心就是把一我的的消息廣播給全部人,咱們這裏使用WebSocket技術讓全部人的瀏覽器都與服務器連在一塊兒,當一我的發送消息到服務器後,服務器把消息轉發給全部人,包括本身,

這樣每一個人的瀏覽器就都能看到這條消息。

出現一條新消息時必備的3個屬性:【發言人暱稱】,【消息內容】和【發送時間】。

爲了區別消息是否爲本身,咱們還須要在消息中加入一項屬性:【是否本身】。

其中【發送時間】和【是否本身】能夠由服務器進行處理,那麼發言人只須要告訴服務器【暱稱】與【消息內容】便可:

//瀏覽器發給服務器的數據:
{
    nickname:"風清揚",
    content:"HelloWorld"
}
//瀏覽器接收的數據:
{
    nickname:"風清揚",
    content:"HelloWorld",
    date:"2016.04.01 14:05:22",
    isSelf:true
}

 

55、JS添加新消息

頁面樣式已經設計好,而真正聊天的時候確定須要不斷展現新的消息,爲了方便控制,咱們使用JavaScript統一消息的建立過程。

頁面中表明消息的li元素只保留一份,把它做爲消息的模板,默認隱藏,每當新消息到來,咱們就複製一份模板,修改其中的屬性,追加到列表中去展現,給幾個元素加上獨有的標記: 

【暱稱】:ff="nickname" 【內容】:ff="content" 【時間】:ff="msgdate"

<li id="msgtmp" class="am-comment" style="display:none;">
    <a href="">
        <img class="am-comment-avatar" src="assets/images/other.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="">2014-7-12 15:30</time>
            </div>
        </header>
     <div ff="content" class="am-comment-bd">此處是消息內容</div>
    </div>
</li>

使用JS克隆一份模板,設置克隆體裏面的數據,最終追加到列表中:

//向聊天窗口加入一條消息
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);  //滾動條移動至最底部
}

66、編寫後臺代碼

新建一個com.zhenzhigu.chat的包,在包中建立一個名爲ChatServer的類,從JavaEE 7開始就統一了WebSocket的API,所以不管是什麼服務器,用Java寫的代碼都是同樣的,代碼以下:

package com.zhenzhigu.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 net.sf.json.JSONObject;
@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);
    }
    /**
     * 接收到來自用戶的消息
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message,Session session){
        //把用戶發來的消息解析爲JSON對象
        JSONObject obj = JSONObject.fromObject(message);
        //向JSON對象中添加發送時間
        obj.put("date", df.format(new Date()));
        //遍歷聊天室中的全部會話
        for(Session se : room){
            //設置消息是否爲本身的
            obj.put("isSelf", se.equals(session));
            //發送消息給遠程用戶
            se.getAsyncRemote().sendText(obj.toString());
        }
    }
    /**
     * 用戶斷開
     * @param session
     */
    @OnClose
    public void onClose(Session session){
        room.remove(session);
    }
    /**
     * 用戶鏈接異常
     * @param t
     */
    @OnError
    public void onError(Throwable t){
    }
}

 

77、前端後端交互

後臺寫完了,前臺要用WebSocket鏈接後臺,須要新建一個WebSocket對象,而後就能夠和服務器端進行交互,從瀏覽器發送消息給服務器端,同時要驗證輸入框的內容是否爲空,而後接受服務端發送的消息,把它們動態地添加到聊天內容框中。

記得寫到文檔就緒函數中

//本身的暱稱
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();
    }
});

到這步,簡單的網頁聊天室就完成了,你能夠多開幾個窗口或在局域網中邀請小夥伴們來一塊兒測試。

88、思考

本次項目只是簡單的實現羣體聊天功能,還有不少功能能夠增長,例如頭像上傳、一對一聊天等,請考慮如何完善咱們的聊天室。

相關文章
相關標籤/搜索