WebSocket笔记②——利用WebSocket实现点对点聊天(待完善)

点对点聊天工程

采用的springboot框架搭建的mvc项目

依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
        <version>2.0.5.RELEASEversion>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-websocketartifactId>
        <version>2.0.5.RELEASEversion>
    dependency>
    <dependency>
        <groupId>org.webjarsgroupId>
        <artifactId>webjars-locator-coreartifactId>
        <version>0.40version>
    dependency>
    <dependency>
        <groupId>org.webjarsgroupId>
        <artifactId>sockjs-clientartifactId>
        <version>1.0.2version>
    dependency>
    <dependency>
        <groupId>org.webjarsgroupId>
        <artifactId>stomp-websocketartifactId>
        <version>2.3.3version>
    dependency>
    <dependency>
        <groupId>org.webjarsgroupId>
        <artifactId>bootstrapartifactId>
        <version>3.3.7version>
    dependency>
    <dependency>
        <groupId>org.webjarsgroupId>
        <artifactId>jqueryartifactId>
        <version>3.1.0version>
    dependency>
dependencies>

前端

这里是采用的layui框架搭建的一个简单页面,总共有三个页面,登陆页面、聊天页面和主页面。

js和css文件

layui的js、css和图片文件,还有layui依赖的jquery框架
WebSocket笔记②——利用WebSocket实现点对点聊天(待完善)_第1张图片

登陆页面


<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>layout 后台大布局 - Layuititle>
    <link rel="stylesheet" href="/layui/css/layui.css">
head>
    <body>
        <div id="loginForm" style="width: 500px">
            <form class="layui-form" action="/login" method="post">
                <div class="layui-form-item" style="padding-top:10px;">
                    <label class="layui-form-label">用戶名label>
                    <div class="layui-input-inline">
                        <input type="text" name="username" required  lay-verify="required" placeholder="请输入用戶名" autocomplete="off" class="layui-input">
                    div>
                div>
                <div class="layui-form-item">
                    <label class="layui-form-label">密码框label>
                    <div class="layui-input-inline">
                        <input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
                    div>
                    <div class="layui-form-mid layui-word-aux">辅助文字div>
                div>

                <div class="layui-form-item">
                    <div class="layui-input-block">
                        <button class="layui-btn" id="luban" lay-submit lay-filter="luban">立即提交button>
                        <button type="reset" class="layui-btn layui-btn-primary">重置button>
                    div>
                div>
            form>
        div>
    body>


<script src="jquery.js">script>
<script src="/layui/layui.js">script>
<script>

    layui.use('layer', function() {
        layer.open({
            type: 1,
            content: $('#loginForm'),
            maxWidth: 600
        });
    });

script>
html>

主界面


<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>layout 后台大布局 - Layuititle>
    <link rel="stylesheet" href="/layui/css/layui.css">
head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
    <div class="layui-header">
        <div class="layui-logo">layui 后台布局div>
        
        <ul class="layui-nav layui-layout-left">
            <li class="layui-nav-item"><a href="">控制台a>li>
            <li class="layui-nav-item"><a href="">商品管理a>li>
            <li class="layui-nav-item"><a href="">用户a>li>
            <li class="layui-nav-item">
                <a href="javascript:;">其它系统a>
                <dl class="layui-nav-child">
                    <dd><a href="">邮件管理a>dd>
                    <dd><a href="">消息管理a>dd>
                    <dd><a href="">授权管理a>dd>
                dl>
            li>
        ul>
        <ul class="layui-nav layui-layout-right">
            <li class="layui-nav-item">
                <a href="javascript:;">
                    <img src="http://t.cn/RCzsdCq" class="layui-nav-img">
                    贤心
                a>
                <dl class="layui-nav-child">
                    <dd><a href="">基本资料a>dd>
                    <dd><a href="">安全设置a>dd>
                dl>
            li>
            <li class="layui-nav-item"><a href="">退了a>li>
        ul>
    div>

    <div class="layui-side layui-bg-black">
        <div class="layui-side-scroll">
            
            <ul class="layui-nav layui-nav-tree"  lay-filter="test" id="onLine">

            ul>
        div>
    div>

    <div class="layui-body">
        
        <div style="padding: 15px;">内容主体区域div>
    div>

    <div class="layui-footer">
        
        © layui.com - 底部固定区域
    div>

    
    <input id="sendUsername">

div>
<script src="/layui/layui.js">script>
<script src="/jquery.js">script>
<script src="/webjars/sockjs-client/1.0.2/sockjs.min.js">script>
<script src="/webjars/stomp-websocket/2.3.3/stomp.min.js">script>
<script src="app.js">script>


<script>
    //JavaScript代码区域
    layui.use('element', function(){
        var element = layui.element;
        // element.render("nav");
    });

    $(function(){
        var info="";
        $.ajax({
            url:"/userInfo",//发送在线人数给所有客户端
            type:"post",
            dataType:"json",
            success:function(data){
                console.log(data);
                info=data.info;
            }

        });
        //连接ws
        var socket = new SockJS('/luban');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function (frame) {
            //订阅-------获取在线人数
            stompClient.subscribe('/topic/userList', function (data) {
                initOnLine(data.body)
            });
            //訂閲  聊天的消息,發給我
            stompClient.subscribe('/user/'+info+"/luban", function (data) {
                console.log(data);
            });

            $.ajax({
                url:"/userList",//发送在线人数给所有客户端
                type:"post",
                dataType:"json",
                success:function(data){

                }

            })
        });



    })


    function chat(obj){

        //把sendToUserName存到一个input
        $("#sendUsername").val(obj);

        layui.use('layer', function() {
            layer.open({
                area: ['700px', '900px'],
                type: 2,
                content: 'chat.html',
                maxWidth: 600,
            });
        });

    }
    function initOnLine(data){
        //user1,user2,user3,user4
        data = data.split(",");
        //[user1,user2.....]
        $("#onLine").html("");

        $.each(data,function(i,v){
            $("#onLine").append(" 
  • +v+"\')\">"+v+"
  • "
    ); }) }
    script> body> html>

    聊天页面

       
    <html>   
    <head>   
        <meta charset="UTF-8">   
        <title>HTML5模拟微信聊天界面title> 
    	<style>
    		#container{
    			    border-radius: 10px;
    				width: 450px;
    				height: 700px;
    				background: #f3f2f2;
    				margin: 80px auto;
    				position: relative;
    				box-shadow: 10px 40px 55px #e8e5e5;
    		}
    		#header{
    			    background: #191818;
    				height: 50px;
    				color: #fff;
    				border-radius: 2px;
    				line-height: 50px;
    				text-align: center;
    				font-size: 12px;
    		}
    		#footer{
    				text-align:center;
    				position: absolute;
    				bottom: 0;
    				background: #1f1e1e;
    				width: 450px;
    				height: 50px;
    				border-radius: 2px;
    		}
    		
    		#footer input{
    				padding-left: 6px;
    				float:left;
    				width: 360px;
    				height: 30px;
    				border-radius: 6px;
    				margin: 8px 10px;
    				border: 0px;
    		}
    		#sendButton{
    				font-weight: 800;
    				font-size: 10px;
    				background: #0e8007;
    				width: 45px;
    				height: 30px;
    				float: left;
    				line-height: 30px;
    				margin: 8px;
    				border-radius: 4px;
    				cursor: pointer;
    		}
    		#content{
    				overflow: auto;
    				height:600px;
    				width:450px;
    				margin:0;
    				padding:5px;
    				list-style: none;
    		}
    		#content li{
    			list-style-type:none;
    			clear: both;
    			overflow: hidden;
    		
    		}
    		.msg{
    			padding: 10px;
    			max-width: 300px;
    			height: 30px;
    			background: #7cbb55;
    			float: right;
    			margin-right: 10px;
    			border-radius: 6px;
    			line-height: 30px;
    			text-align: center;
    		}
    	style>
    head>
    	<body>
    		<div id="container">
    			<div id="header">
    				安琪拉小姐姐
    			div>
    			
    			<ul id="content">
    				<li>
    					<div class="msg">
    						fdsfsdfdsfdsfds
    					<div>
    				li>
    			ul>
    			
    			<div id="footer">
    				<div id="sendBox">
    					<input id="sendVal">
    				div>
    				<div id="sendButton">发送div>
    			div>
    			
    		div>
    	body>
    <script src="/jquery.js">script>
    <script src="/webjars/sockjs-client/1.0.2/sockjs.min.js">script>
    <script src="/webjars/stomp-websocket/2.3.3/stomp.min.js">script>
    <script>
    	var sendToname ="";//發送給誰
        var info = "";//自己是誰
        $(function() {
            sendToname = parent.$("#sendUsername").val();
            $("#sendButton").click(function () {
                var chatMsg = $("#sendVal").val();
                $.ajax({
                    url: "/chat",//发送在线人数给所有客户端
                    type: "post",
    				data:'message='+chatMsg+'&username='+sendToname,
                    dataType: "json",
                    success: function (data) {
                        //info = data.info;
                    }
                });
            });
    
    
    
    
            var socket = new SockJS('/luban');
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function (frame) {
                console.log(sendToname+"pppppppppppppppppppppppp")
                //訂閲  聊天的消息,發給我
                stompClient.subscribe('/user/' +info+"/luban", function (data) {
                    console.log(data);
                });
    
            });
    
        })
    
    script>
    html>
    

    后端

    websocket配置类

    需要注册相关的订阅路径,配置监听的路径

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry config) {
            //允许订阅的前缀
            config.enableSimpleBroker("/topic","/user");
    
            //路由到controller
            config.setApplicationDestinationPrefixes("/app");
        }
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/luban").withSockJS();
        }
    
    }
    

    Controller

    package com.luban.web;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.messaging.simp.SimpMessagingTemplate;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @Controller
    public class LubanController {
    
        @Autowired
        SimpMessagingTemplate template;
    
    
        /**
         * 登录的controller
         * @param username
         * @param request
         * @param response
         * @throws IOException
         */
        @RequestMapping("/login")
        public void login(String username, HttpServletRequest request, HttpServletResponse response) throws IOException {
            //维护一个在线人员的列表
            Contains.list.add(username);
            //把当前登录人存到session
            request.getSession().setAttribute("uname",username);
            response.sendRedirect("main.html");
        }
    
    
        /**
         * 获取当前登录的用户信息
         * @param request
         * @param response
         * @return
         * @throws IOException
         */
        @RequestMapping("/userInfo")
        @ResponseBody
        public String login(HttpServletRequest request, HttpServletResponse response) throws IOException {
            String info = request.getSession().getAttribute("uname").toString();
            return "{\"info\":\""+info+"\"}";
        }
    
        /**
         * server 更新在线人数列表的方法
         * 他会给所有订阅了/topic/userList的ws客户端发送消息
         * @return
         */
        @RequestMapping("/userList")
        @ResponseBody
        public String userList(){
            String allUser="";
            for (String s : Contains.list) {
                allUser+=s+",";
            }
            allUser =   allUser.substring(0,allUser.length()-1);
            template.convertAndSend("/topic/userList",allUser);
            return "success";
        }
    
    
        /**
         * 客户端发送消息方法
         * @param message
         * @param username
         * @return
         */
        @RequestMapping("/chat")
        @ResponseBody
        public String chat(String message,String username){
            System.out.println("-------------------"+message+"---"+username);
            //convertAndSend("/user/'user3'/luban")
            template.convertAndSendToUser(username,"luban",message);
            return  "success";
        }
    }
    

    下面的类是做缓存作用的

    public class Contains {
    
        public static List<String> list = new ArrayList();
    }
    

    启动类

    @SpringBootApplication
    public class Testws {
        public static void main(String[] args) {
            SpringApplication.run(Testws.class);
        }
    }
    

    效果

    • 登陆界面

    WebSocket笔记②——利用WebSocket实现点对点聊天(待完善)_第2张图片

    • 主界面

    左侧显示在线人员
    WebSocket笔记②——利用WebSocket实现点对点聊天(待完善)_第3张图片

    • 聊天界面

    点击左侧的其他用户会弹出聊天窗口
    WebSocket笔记②——利用WebSocket实现点对点聊天(待完善)_第4张图片
    在聊天框中输入消息后点击发送消息
    WebSocket笔记②——利用WebSocket实现点对点聊天(待完善)_第5张图片
    可以收到发送过来的消息
    WebSocket笔记②——利用WebSocket实现点对点聊天(待完善)_第6张图片

    整体架构图

    WebSocket笔记②——利用WebSocket实现点对点聊天(待完善)_第7张图片

    你可能感兴趣的:(WebSocket笔记)