WebSocket+Java 私聊、羣聊實例

   前言

  以前寫畢業設計的時候就想加上聊天系統,當時已經用ajax長輪詢實現了一個(還不懂什麼是輪詢機制的,猛戳這裏:https://www.cnblogs.com/hoojo/p/longPolling_comet_jquery_iframe_ajax.html),但因爲種種緣由沒有加到畢設裏面。後來回校答辯後研究了一下websocket,並參照網上資料寫了一個簡單的聊天,如今又從新整理並記錄下來。

  如下介紹來自維基百科:
  WebSocket是一種在單個TCP鏈接上進行全雙工通訊的協議。WebSocket通訊協議於2011年被IETF定爲標準RFC 6455,並由RFC7936補充規範。WebSocket API也被W3C定爲標準。
WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。

  這裏能夠看一下官網介紹:http://www.websocket.org/aboutwebsocket.html
  官網裏面介紹很是詳細,我就不作搬運工了,要是有像我同樣英語很差的同窗,右鍵->翻譯成簡體中文

  spring對websocket的支持:https://docs.spring.io/spring/docs/4.3.13.RELEASE/spring-framework-reference/htmlsingle/#websocket
  這裏有一份spring對websocket的詳細介紹:https://docs.spring.io/spring/docs/5.1.8.RELEASE/spring-framework-reference/web.html#websocket
javascript

  四個大章節,內容不少,就不一一展開介紹了css

  

 

  效果

  2019/04/30補充:咱們這個登陸、登出很是簡單,就一個請求地址,連頁面都沒有,因此剛開始我就沒有貼出來,致使博客文章閱讀起來比較吃力,如今在這裏補充一下(因爲項目後面有所改動,請求地址少了 springboot/,不過你們看得懂就行),這裏只是一個小demo,全部就怎麼簡單怎麼來html

  登陸 http://localhost:10086/websocket/login/huanzi,java

  登出 http://localhost:10086/websocket/logout/huanzijquery

    

  上下線有提示git

 

 

  若是這時候發送消息給離線的人,則會收到系統提示消息github

 

  羣聊

  本例中,點擊本身是羣聊窗口web

  huanzi一發送羣聊,laowang跟xiaofang都不是在當前羣聊窗口,出現小圓點+1ajax

 

  

  huanzi一發送羣聊,xiaofang在當前羣聊窗口,直接追加消息,老王不在對應的聊天窗口,出現小圓點+1spring

 

  xiaofang回覆,huanzi直接追加消息,laowang依舊小圓點+1

 

  laowang點擊羣聊窗口,小圓點消失,追加羣聊消息

 

  laowang參與羣聊

 

  xiaofang切出羣聊窗口,laowang在羣聊發送消息,xiaofang出現小圓點+1

 

  切回來,小圓點消失,聊天數據正常接收追加

 

  三方正常參與聊天

 

  私聊

  huanzis私聊xiaofang,xiaofang聊天窗口在羣聊,小圓點+1,而laowang不受影響

 

   xiaofang切到私聊窗口,小圓點消失,數據正常追加;huanzi恰好處於私聊窗口,數據直接追加

 

   效果演示到此結束,下面貼出代碼

 

  代碼編寫

  首先先介紹一下項目結構

 

  maven

        <!-- springboot websocket -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <!-- thymeleaf模板 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

  配置文件

#修改thymeleaf訪問根路徑
spring.thymeleaf.prefix=classpath:/view/

 

socketChart.css樣式
body{
    background-color: #efebdc;
}
#hz-main{
    width: 700px;
    height: 500px;
    background-color: red;
    margin: 0 auto;
}

#hz-message{
    width: 500px;
    height: 500px;
    float: left;
    background-color: #B5B5B5;
}

#hz-message-body{
    width: 460px;
    height: 340px;
    background-color: #E0C4DA;
    padding: 10px 20px;
    overflow:auto;
}

#hz-message-input{
    width: 500px;
    height: 99px;
    background-color: white;
    overflow:auto;
}

#hz-group{
    width: 200px;
    height: 500px;
    background-color: rosybrown;
    float: right;
}

.hz-message-list{
    min-height: 30px;
    margin: 10px 0;
}
.hz-message-list-text{
    padding: 7px 13px;
    border-radius: 15px;
    width: auto;
    max-width: 85%;
    display: inline-block;
}

.hz-message-list-username{
    margin: 0;
}

.hz-group-body{
    overflow:auto;
}

.hz-group-list{
    padding: 10px;
}

.left{
    float: left;
    color: #595a5a;
    background-color: #ebebeb;
}
.right{
    float: right;
    color: #f7f8f8;
    background-color: #919292;
}
.hz-badge{
    width: 20px;
    height: 20px;
    background-color: #FF5722;
    border-radius: 50%;
    float: right;
    color: white;
    text-align: center;
    line-height: 20px;
    font-weight: bold;
    opacity: 0;
}

 

  

socketChart.html頁面
<!DOCTYPE>
<!--解決idea thymeleaf 表達式模板報紅波浪線-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>聊天頁面</title>
    <!-- jquery在線版本 -->
    <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
    <!--引入樣式-->
    <link th:href="@{/css/socketChart.css}" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="hz-main">
    <div id="hz-message">
        <!-- 頭部 -->
        正在與<span id="toUserName"></span>聊天
        <hr style="margin: 0px;"/>
        <!-- 主體 -->
        <div id="hz-message-body">
        </div>
        <!-- 功能條 -->
        <div id="">
            <button>表情</button>
            <button>圖片</button>
            <button id="videoBut">視頻</button>
            <button onclick="send()" style="float: right;">發送</button>
        </div>
        <!-- 輸入框 -->
        <div contenteditable="true" id="hz-message-input">

        </div>
    </div>
    <div id="hz-group">
        登陸用戶:<span id="talks" th:text="${username}">請登陸</span>
        <br/>
        在線人數:<span id="onlineCount">0</span>
        <!-- 主體 -->
        <div id="hz-group-body">

        </div>
    </div>
</div>
</body>
<script type="text/javascript" th:inline="javascript">
    //項目根路徑
    var ctx = [[${#request.getContextPath()}]];//登陸名
    var username = /*[[${username}]]*/'';
</script>
<script th:src="@{/js/socketChart.js}"></script>
</html>

 

  

socketChart.js 邏輯代碼
    //消息對象數組
    var msgObjArr = new Array();

    var websocket = null;

    //判斷當前瀏覽器是否支持WebSocket, springboot是項目名
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://localhost:10086/springboot/websocket/"+username);
    } else {
        console.error("不支持WebSocket");
    }

    //鏈接發生錯誤的回調方法
    websocket.onerror = function (e) {
        console.error("WebSocket鏈接發生錯誤");
    };

    //鏈接成功創建的回調方法
    websocket.onopen = function () {
        //獲取全部在線用戶
        $.ajax({
            type: 'post',
            url: ctx + "/websocket/getOnlineList",
            contentType: 'application/json;charset=utf-8',
            dataType: 'json',
            data: {username:username},
            success: function (data) {
                if (data.length) {
                    //列表
                    for (var i = 0; i < data.length; i++) {
                        var userName = data[i];
                        $("#hz-group-body").append("<div class=\"hz-group-list\"><span class='hz-group-list-username'>" + userName + "</span><span id=\"" + userName + "-status\">[在線]</span><div id=\"hz-badge-" + userName + "\" class='hz-badge'>0</div></div>");
                    }

                    //在線人數
                    $("#onlineCount").text(data.length);
                }
            },
            error: function (xhr, status, error) {
                console.log("ajax錯誤!");
            }
        });
    }

    //接收到消息的回調方法
    websocket.onmessage = function (event) {
        var messageJson = eval("(" + event.data + ")");

        //普通消息(私聊)
        if (messageJson.type == "1") {
            //來源用戶
            var srcUser = messageJson.srcUser;
            //目標用戶
            var tarUser = messageJson.tarUser;
            //消息
            var message = messageJson.message;

            //最加聊天數據
            setMessageInnerHTML(srcUser.username,srcUser.username, message);
        }

        //普通消息(羣聊)
        if (messageJson.type == "2"){
            //來源用戶
            var srcUser = messageJson.srcUser;
            //目標用戶
            var tarUser = messageJson.tarUser;
            //消息
            var message = messageJson.message;

            //最加聊天數據
            setMessageInnerHTML(username,tarUser.username, message);
        }

        //對方不在線
        if (messageJson.type == "0"){
            //消息
            var message = messageJson.message;

            $("#hz-message-body").append(
                "<div class=\"hz-message-list\" style='text-align: center;'>" +
                    "<div class=\"hz-message-list-text\">" +
                        "<span>" + message + "</span>" +
                    "</div>" +
                "</div>");
        }

        //在線人數
        if (messageJson.type == "onlineCount") {
            //取出username
            var onlineCount = messageJson.onlineCount;
            var userName = messageJson.username;
            var oldOnlineCount = $("#onlineCount").text();

            //新舊在線人數對比
            if (oldOnlineCount < onlineCount) {
                if($("#" + userName + "-status").length > 0){
                    $("#" + userName + "-status").text("[在線]");
                }else{
                    $("#hz-group-body").append("<div class=\"hz-group-list\"><span class='hz-group-list-username'>" + userName + "</span><span id=\"" + userName + "-status\">[在線]</span><div id=\"hz-badge-" + userName + "\" class='hz-badge'>0</div></div>");
                }
            } else {
                //有人下線
                $("#" + userName + "-status").text("[離線]");
            }
            $("#onlineCount").text(onlineCount);
        }

    }

    //鏈接關閉的回調方法
    websocket.onclose = function () {
        //alert("WebSocket鏈接關閉");
    }

    //將消息顯示在對應聊天窗口    對於接收消息來講這裏的toUserName就是來源用戶,對於發送來講則相反
    function setMessageInnerHTML(srcUserName,msgUserName, message) {
        //判斷
        var childrens = $("#hz-group-body").children(".hz-group-list");
        var isExist = false;
        for (var i = 0; i < childrens.length; i++) {
            var text = $(childrens[i]).find(".hz-group-list-username").text();
            if (text == srcUserName) {
                isExist = true;
                break;
            }
        }
        if (!isExist) {
            //追加聊天對象
            msgObjArr.push({
                toUserName: srcUserName,
                message: [{username: msgUserName, message: message, date: NowTime()}]//封裝數據
            });
            $("#hz-group-body").append("<div class=\"hz-group-list\"><span class='hz-group-list-username'>" + srcUserName + "</span><span id=\"" + srcUserName + "-status\">[在線]</span><div id=\"hz-badge-" + srcUserName + "\" class='hz-badge'>0</div></div>");
        } else {
            //取出對象
            var isExist = false;
            for (var i = 0; i < msgObjArr.length; i++) {
                var obj = msgObjArr[i];
                if (obj.toUserName == srcUserName) {
                    //保存最新數據
                    obj.message.push({username: msgUserName, message: message, date: NowTime()});
                    isExist = true;
                    break;
                }
            }
            if (!isExist) {
                //追加聊天對象
                msgObjArr.push({
                    toUserName: srcUserName,
                    message: [{username: msgUserName, message: message, date: NowTime()}]//封裝數據
                });
            }
        }

        // 對於接收消息來講這裏的toUserName就是來源用戶,對於發送來講則相反
        var username = $("#toUserName").text();

        //恰好打開的是對應的聊天頁面
        if (srcUserName == username) {
            $("#hz-message-body").append(
                "<div class=\"hz-message-list\">" +
                    "<p class='hz-message-list-username'>"+msgUserName+":</p>" +
                "<div class=\"hz-message-list-text left\">" +
                    "<span>" + message + "</span>" +
                "</div>" +
                "<div style=\" clear: both; \"></div>" +
                "</div>");
        } else {
            //小圓點++
            var conut = $("#hz-badge-" + srcUserName).text();
            $("#hz-badge-" + srcUserName).text(parseInt(conut) + 1);
            $("#hz-badge-" + srcUserName).css("opacity", "1");
        }
    }

    //發送消息
    function send() {
        //消息
        var message = $("#hz-message-input").html();
        //目標用戶名
        var tarUserName = $("#toUserName").text();
        //登陸用戶名
        var srcUserName = $("#talks").text();
        websocket.send(JSON.stringify({
            "type": "1",
            "tarUser": {"username": tarUserName},
            "srcUser": {"username": srcUserName},
            "message": message
        }));
        $("#hz-message-body").append(
            "<div class=\"hz-message-list\">" +
            "<div class=\"hz-message-list-text right\">" +
            "<span>" + message + "</span>" +
            "</div>" +
            "</div>");
        $("#hz-message-input").html("");
        //取出對象
        if (msgObjArr.length > 0) {
            var isExist = false;
            for (var i = 0; i < msgObjArr.length; i++) {
                var obj = msgObjArr[i];
                if (obj.toUserName == tarUserName) {
                    //保存最新數據
                    obj.message.push({username: srcUserName, message: message, date: NowTime()});
                    isExist = true;
                    break;
                }
            }
            if (!isExist) {
                //追加聊天對象
                msgObjArr.push({
                    toUserName: tarUserName,
                    message: [{username: srcUserName, message: message, date: NowTime()}]//封裝數據[{username:huanzi,message:"你好,我是歡子!",date:2018-04-29 22:48:00}]
                });
            }
        } else {
            //追加聊天對象
            msgObjArr.push({
                toUserName: tarUserName,
                message: [{username: srcUserName, message: message, date: NowTime()}]//封裝數據[{username:huanzi,message:"你好,我是歡子!",date:2018-04-29 22:48:00}]
            });
        }
    }

    //監聽點擊用戶
    $("body").on("click", ".hz-group-list", function () {
        $(".hz-group-list").css("background-color", "");
        $(this).css("background-color", "whitesmoke");
        $("#toUserName").text($(this).find(".hz-group-list-username").text());

        //清空舊數據,從對象中取出並追加
        $("#hz-message-body").empty();
        $("#hz-badge-" + $("#toUserName").text()).text("0");
        $("#hz-badge-" + $("#toUserName").text()).css("opacity", "0");
        if (msgObjArr.length > 0) {
            for (var i = 0; i < msgObjArr.length; i++) {
                var obj = msgObjArr[i];
                if (obj.toUserName == $("#toUserName").text()) {
                    //追加數據
                    var messageArr = obj.message;
                    if (messageArr.length > 0) {
                        for (var j = 0; j < messageArr.length; j++) {
                            var msgObj = messageArr[j];
                            var leftOrRight = "right";
                            var message = msgObj.message;
                            var msgUserName = msgObj.username;
                            var toUserName = $("#toUserName").text();

                            //當聊天窗口與msgUserName的人相同,文字在左邊(對方/其餘人),不然在右邊(本身)
                            if (msgUserName == toUserName) {
                                leftOrRight = "left";
                            }

                            //可是若是點擊的是本身,羣聊的邏輯就不太同樣了
                            if (username == toUserName && msgUserName != toUserName) {
                                leftOrRight = "left";
                            }

                            if (username == toUserName && msgUserName == toUserName) {
                                leftOrRight = "right";
                            }

                            var magUserName = leftOrRight == "left" ? "<p class='hz-message-list-username'>"+msgUserName+":</p>" : "";

                            $("#hz-message-body").append(
                                "<div class=\"hz-message-list\">" +
                                magUserName+
                                "<div class=\"hz-message-list-text " + leftOrRight + "\">" +
                                    "<span>" + message + "</span>" +
                                "</div>" +
                                "<div style=\" clear: both; \"></div>" +
                                "</div>");
                        }
                    }
                    break;
                }
            }
        }
    });

    //獲取當前時間
    function NowTime() {
        var time = new Date();
        var year = time.getFullYear();//獲取年
        var month = time.getMonth() + 1;//或者月
        var day = time.getDate();//或者天
        var hour = time.getHours();//獲取小時
        var minu = time.getMinutes();//獲取分鐘
        var second = time.getSeconds();//或者秒
        var data = year + "-";
        if (month < 10) {
            data += "0";
        }
        data += month + "-";
        if (day < 10) {
            data += "0"
        }
        data += day + " ";
        if (hour < 10) {
            data += "0"
        }
        data += hour + ":";
        if (minu < 10) {
            data += "0"
        }
        data += minu + ":";
        if (second < 10) {
            data += "0"
        }
        data += second;
        return data;
    }

 

  java代碼有三個類,MyEndpointConfigure,WebSocketConfig,WebSocketServer;

  MyEndpointConfigure

/**
 * 解決注入其餘類的問題,詳情參考這篇帖子:webSocket沒法注入其餘類:https://blog.csdn.net/tornadojava/article/details/78781474
 */
public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {

    private static volatile BeanFactory context;

    @Override
    public <T> T getEndpointInstance(Class<T> clazz){
        return context.getBean(clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyEndpointConfigure.context = applicationContext;
    }
}

 

  WebSocketConfig

/**
 * WebSocket配置
 */
@Configuration
public class WebSocketConfig{


    /**
     * 用途:掃描並註冊全部攜帶@ServerEndpoint註解的實例。 @ServerEndpoint("/websocket")
     * PS:若是使用外部容器 則無需提供ServerEndpointExporter。
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    /**
     * 支持注入其餘類
     */
    @Bean
    public MyEndpointConfigure  newMyEndpointConfigure (){
        return new MyEndpointConfigure ();
    }
}

 

  WebSocketServer

/**
 * WebSocket服務
 */
@RestController
@RequestMapping("/websocket")
@ServerEndpoint(value = "/websocket/{username}", configurator = MyEndpointConfigure.class)
public class WebSocketServer {

    /**
     * 在線人數
     */
    private static int onlineCount = 0;

    /**
     * 在線用戶的Map集合,key:用戶名,value:Session對象
     */
    private static Map<String, Session> sessionMap = new HashMap<String, Session>();

    /**
     * 注入其餘類(換成本身想注入的對象)
     */
    @Autowired
    private UserService userService;

    /**
     * 鏈接創建成功調用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        //在webSocketMap新增上線用戶
        sessionMap.put(username, session);

        //在線人數加加
        WebSocketServer.onlineCount++;

        //通知除了本身以外的全部人
        sendOnlineCount(session, "{'type':'onlineCount','onlineCount':" + WebSocketServer.onlineCount + ",username:'" + username + "'}");
    }

    /**
     * 鏈接關閉調用的方法
     */
    @OnClose
    public void onClose(Session session) {
        //下線用戶名
        String logoutUserName = "";

        //從webSocketMap刪除下線用戶
        for (Entry<String, Session> entry : sessionMap.entrySet()) {
            if (entry.getValue() == session) {
                sessionMap.remove(entry.getKey());
                logoutUserName = entry.getKey();
                break;
            }
        }
        //在線人數減減
        WebSocketServer.onlineCount--;

        //通知除了本身以外的全部人
        sendOnlineCount(session, "{'type':'onlineCount','onlineCount':" + WebSocketServer.onlineCount + ",username:'" + logoutUserName + "'}");
    }

    /**
     * 服務器接收到客戶端消息時調用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            //JSON字符串轉 HashMap
            HashMap hashMap = new ObjectMapper().readValue(message, HashMap.class);

            //消息類型
            String type = (String) hashMap.get("type");

            //來源用戶
            Map srcUser = (Map) hashMap.get("srcUser");

            //目標用戶
            Map tarUser = (Map) hashMap.get("tarUser");

            //若是點擊的是本身,那就是羣聊
            if (srcUser.get("username").equals(tarUser.get("username"))) {
                //羣聊
                groupChat(session,hashMap);
            } else {
                //私聊
                privateChat(session, tarUser, hashMap);
            }

            //後期要作消息持久化

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 發生錯誤時調用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 通知除了本身以外的全部人
     */
    private void sendOnlineCount(Session session, String message) {
        for (Entry<String, Session> entry : sessionMap.entrySet()) {
            try {
                if (entry.getValue() != session) {
                    entry.getValue().getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 私聊
     */
    private void privateChat(Session session, Map tarUser, HashMap hashMap) throws IOException {
        //獲取目標用戶的session
        Session tarUserSession = sessionMap.get(tarUser.get("username"));

        //若是不在線則發送「對方不在線」回來源用戶
        if (tarUserSession == null) {
            session.getBasicRemote().sendText("{\"type\":\"0\",\"message\":\"對方不在線\"}");
        } else {
            hashMap.put("type", "1");
            tarUserSession.getBasicRemote().sendText(new ObjectMapper().writeValueAsString(hashMap));
        }
    }

    /**
     * 羣聊
     */
    private void groupChat(Session session,HashMap hashMap) throws IOException {
        for (Entry<String, Session> entry : sessionMap.entrySet()) {
            //本身就不用再發送消息了
            if (entry.getValue() != session) {
                hashMap.put("type", "2");
                entry.getValue().getBasicRemote().sendText(new ObjectMapper().writeValueAsString(hashMap));
            }
        }
    }

    /**
     * 登陸
     */
    @RequestMapping("/login/{username}")
    public ModelAndView login(HttpServletRequest request, @PathVariable String username) {
        return new ModelAndView("socketChart.html", "username", username);
    }

    /**
     * 登出
     */
    @RequestMapping("/logout/{username}")
    public String loginOut(HttpServletRequest request, @PathVariable String username) {
        return "退出成功!";
    }

    /**
     * 獲取在線用戶
     */
    @RequestMapping("/getOnlineList")
    private List<String> getOnlineList(String username) {
        List<String> list = new ArrayList<String>();
        //遍歷webSocketMap
        for (Entry<String, Session> entry : WebSocketServer.sessionMap.entrySet()) {
            if (!entry.getKey().equals(username)) {
                list.add(entry.getKey());
            }
        }
        return list;
    }

}

 

  後記

  後期把全部功能都補全就完美了,表情、圖片都算比較簡單,以前用輪詢實現的時候寫過了,可是沒加到這裏來;音視頻聊天的話能夠用WbeRTC來作,以前也研究了一下,不過還沒搞完,這裏貼一下維基百科對它的介紹,想了解更多的自行Google:

  WebRTC,名稱源自網頁即時通訊(英語:Web Real-Time Communication)的縮寫,是一個支持網頁瀏覽器進行實時語音對話或視頻對話的API。它於2011年6月1日開源並在Google、Mozilla、Opera支持下被歸入萬維網聯盟的W3C推薦標準。

  最後在加上持久化存儲,註冊後才能聊天,離線消息上線後接收,再加上用Redis或者其餘的緩存技術支持,完美。不過聊天記錄要作存儲,表設計不知如何設計才合理,若是哪位大佬願意分享能夠留言給我,你們一塊兒進步!

 

  補充

  2019-07-03補充:這裏補充貼出pom代碼,在子類引入父類,若是咱們沒有父類,只有一個子類,把兩個整合一下就能夠了

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.huanzi.qch</groupId>
    <artifactId>parent</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/>
    </parent>

    <description>SpringBoot系列demo代碼</description>


    <!-- 在父類引入一下通用的依賴 -->
    <dependencies>
        <!-- spring-boot-starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- springboot web(MVC)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- springboot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--lombok插件 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--熱部署工具dev-tools-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <!--構建工具-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <finalName>${project.artifactId}</finalName>
                    <outputDirectory>../package</outputDirectory>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
parent.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>springboot-websocket</artifactId>
    <version>0.0.1</version>
    <name>springboot-websocket</name>
    <description>SpringBoot系列——WebSocket</description>

    <!--繼承父類-->
    <parent>
        <groupId>cn.huanzi.qch</groupId>
        <artifactId>parent</artifactId>
        <version>1.0.0</version>
    </parent>

    <dependencies>
        <!-- springboot websocket -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <!-- thymeleaf模板 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
springboot-websocket.xml

 

  在後記的部分咱們就提到要加上持久化存儲,事實上咱們已經開始慢慢在寫一套簡單的IM即時通信,已經實現到第三版了,持續更新中...

   一套簡單的web即時通信——初版

  一套簡單的web即時通信——第二版

  一套簡單的web即時通信——第三版

 

 

  代碼開源

  代碼已經開源、託管到個人GitHub、碼雲:

  GitHub:https://github.com/huanzi-qch/springBoot

  碼雲:https://gitee.com/huanzi-qch/springBoot

相關文章
相關標籤/搜索