采用的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框架搭建的一个简单页面,总共有三个页面,登陆页面、聊天页面和主页面。
layui的js、css和图片文件,还有layui依赖的jquery框架
<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>
需要注册相关的订阅路径,配置监听的路径
@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();
}
}
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);
}
}
点击左侧的其他用户会弹出聊天窗口
在聊天框中输入消息后点击发送消息
可以收到发送过来的消息