因为之前用node.js实现过websocket的聊天室,后来在学习SpringBoot时看到WebSocket组件学习,所以就用之前的页面来实现了一遍
demo下载:http://pan.baidu.com/s/1jHUBVBg
演示图
配置pom.xml,引入相关依赖包,webSocket相关包是spring-boot-starter-websocket。
<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.0modelVersion>
<groupId>com.pzrgroupId>
<artifactId>chartroomartifactId>
<version>0.0.1-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>1.5.1.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-autoconfigureartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-websocketartifactId>
<version>1.5.1.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.31version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-jar-pluginartifactId>
<configuration>
<archive>
<manifest>
<addClasspath>trueaddClasspath>
<mainClass>com.pzr.chatroom.LanchermainClass>
manifest>
archive>
configuration>
plugin>
plugins>
build>
project>
springboot的启动程序
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 启动器
* @author pzr
*
*/
@SpringBootApplication
public class Lancher {
public static void main(String[] args) {
SpringApplication.run(Lancher.class, args);
}
}
webSocket的配置类
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
/**
* WebSocketDemo
* @author pzr
*
*/
@Configuration
@EnableWebSocketMessageBroker//开启使用STOMP协议来传输基于代理的消息,支持使用@MessageMapping(类似于@RequestMapping)
public class ChatRoomConfig extends AbstractWebSocketMessageBrokerConfigurer{
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) { //注册STOMP协议节点,并映射指定的URL
registry.addEndpoint("/endpointWisely").withSockJS(); //注册一个STOMP的endpint,并指定使用SocketJS协议
}
}
聊天室的控制器,包含上线,下线,聊天和刷新登录用户列表
1. 使用@MessageMapping(“/talk”)供给前端访问调用
2. 使用@SendTo(“/refreshchatwindow”),将消息发送给监听了refreshchatwindow的客户端
3. 使用template.convertAndSend(“/refreshloginlist”,CacheBean.clientList);,从服务端向监听了refreshchatwindow的客户端发送消息
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import com.pzr.chatroom.entity.CacheBean;
import com.pzr.chatroom.entity.ChatContent;
import com.pzr.chatroom.entity.User;
/**
* 演示控制器
* @author pzr
*
*/
@Controller
public class ChatRoomController {
@Autowired
private SimpMessagingTemplate template;
/**
* 聊天
* @param msg
* @return
*/
@MessageMapping("/talk")//浏览器映射地址
@SendTo("/refreshchatwindow")
public ChatContent talk(ChatContent content) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
content.setDate(sdf.format(new Date()));
return content;
}
/**
* 下线
* @param msg
* @return
*/
@MessageMapping("/downLine")
private void downLine(User msg) {
List list = CacheBean.clientList;
list.remove(msg);
//服务器端通知客户端刷新当前登录人列表
refreshLoginList();
}
/**
* 上线
* @param msg
* @return
*/
@MessageMapping("/upLine")
private void upLine(User msg) {
//内存中将用户加入进来
List list = CacheBean.clientList;
list.add(msg);
//服务器端通知客户端刷新当前登录人列表
refreshLoginList();
}
/**
* 服务器端通知客户端刷新当前登录人列表
* @param list
*/
@MessageMapping("/refreshLoginList")
public void refreshLoginList( ){
template.convertAndSend("/refreshloginlist",CacheBean.clientList);
}
}
/**
*用户实体
*
* @author pzr
*
*/
public class User {
private String uuid;
private String name;
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
}
/**
* 聊天内容
* @author pzr
*
*/
public class ChatContent {
/**
* 时间
*/
public String date;
/**
* 内容
*/
public String content;
/**
* 发送消息的人
*/
public String sendUser;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getSendUser() {
return sendUser;
}
public void setSendUser(String sendUser) {
this.sendUser = sendUser;
}
}
将当前登录人信息存在内存中
import java.util.ArrayList;
import java.util.List;
public class CacheBean {
/**
* 使用静态集合来存储当前登录用户
*/
public static List clientList = new ArrayList();
}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>聊天室title>
<style type="text/css">
style>
<script type="text/javascript" src="js/sockjs.min.js">script>
<script type="text/javascript" src="js/stomp.min.js">script>
<script type="text/javascript">
var nowUUID = "";
var stompClient = null;
window.onload = function() {
//连接服务器
var socket = new SockJS("/endpointWisely");
stompClient = Stomp.over(socket);
//响应事件监听
stompClient.connect({}, function(frame) {
//监听刷新当前登录人列表
stompClient.subscribe("/refreshloginlist", function(respnose) {
var serverObj = JSON.parse(respnose.body);//返回是一个当前登录人数组
var nameArrStr = "";
for (var i = 0; i < serverObj.length; i++) {
nameArrStr = nameArrStr + serverObj[i].name + "\n";
}
console.log(nameArrStr);
userList.value = nameArrStr;
});
//监听刷新聊天窗口
stompClient.subscribe("/refreshchatwindow", function(respnose) {
var serverObj = JSON.parse(respnose.body);//返回是一个当前登录人数组
var contentArea = document.getElementById("contentArea");
var val = contentArea.value;
var returnText = serverObj.sendUser+" "+serverObj.date+":\n "+" "+serverObj.content+"\n ";
contentArea.value = val + returnText;
contentArea.scrollTop = contentArea.scrollHeight;
});
//刷新当前登录用户列表
stompClient.send("/refreshLoginList", {}, {});
});
//键盘事件注册
document.onkeydown = function(event) {
//ctrl+enter发送消息
if (window.event.ctrlKey && window.event.keyCode == 13) {
sendTalk();
}
};
}
//上下线
function upLine() {
var upDownBtn = document.getElementById("upDownBtn");
var uaerNameTxt = document.getElementById("uaerNameTxt");
var uuidLab = document.getElementById("uuidLab");
var userList = document.getElementById("userList");
if (uaerNameTxt.value == "") {
alert("请输入名称!");
return;
}
if (upDownBtn.value == "上线") {
upDownBtn.value = "下线";
uaerNameTxt.readOnly = true;
nowUUID = guid();
uuidLab.innerText=nowUUID;
//上线完成,添加用户
var myObj = new Object();
myObj.uuid = nowUUID;
myObj.name = uaerNameTxt.value;
var json_data = JSON.stringify(myObj);
stompClient.send("/upLine", {}, json_data);
} else {
upDownBtn.value = "上线";
uaerNameTxt.readOnly = false;
//下线完成,删除用户
var myObj = new Object();
myObj.uuid = nowUUID;
var json_data = JSON.stringify(myObj);
stompClient.send("/downLine", {}, json_data);
nowUUID = "";
uuidLab.innerText=nowUUID;
}
}
//发言
function sendTalk() {
var upDownBtn = document.getElementById("upDownBtn");
if (upDownBtn.value == "上线") {
alert("请先上线!");
return;
}
var userName = document.getElementById("uaerNameTxt").value;
var sendContent = document.getElementById("sendContent");
//往服务器发消息
var myObj = new Object();
myObj.sendUser = userName;
myObj.content = sendContent.value;
var json_data = JSON.stringify(myObj);
stompClient.send("/talk", {}, json_data);
sendContent.value = "";
sendContent.focus();
}
//浏览器关闭事件 发起删除登录人消息
window.onbeforeunload = onbeforeunload_handler;
function onbeforeunload_handler() {
//下线完成,删除用户
var myObj = new Object();
myObj.uuid = nowUUID;
var json_data = JSON.stringify(myObj);
stompClient.send("/downLine", {}, json_data);
}
//生成uuid
function guid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r
: (r & 0x3 | 0x8);
return v.toString(16);
});
}
script>
head>
<body style="">
<table border="1"
style="width: 50%;height: 600px; border-color: #00B7FF;margin:0 auto">
<tr height="40px">
<td colspan="4">当前登录人: <input id="uaerNameTxt" type="text"
width="400px" height="100%" /> <input id="upDownBtn" type="button"
value="上线" onclick="upLine()" /> <label id="uuidLab">label>
td>
tr>
<tr>
<td colspan="3"><textarea id="contentArea" name="contentArea"
disabled="disabled"
style="width:100%;height:370px;padding:0px;margin:0px;">textarea>
td>
<td rowspan="3" width="150px"><textarea id="userList"
name="userList" disabled="disabled"
style="width:100%;height:565px;padding:0px;margin:0px;">textarea>
td>
tr>
<tr height="150px">
<td colspan="3"><textarea id="sendContent"
style="width:100%;height:140px;padding:0px;margin:0px;">textarea>
td>
tr>
<tr height="40px">
<td colspan="2">td>
<td width="80px" style="padding:0px;"><input type="button"
onclick="sendTalk()" value="发送"
style="width:100%;height:40px;margin:0px;border:0px;padding:0px;" />
td>
tr>
table>
body>
html>
http://blog.csdn.net/PandaWang1989/article/details/54863489?locationNum=5&fps=1
http://blog.csdn.net/yingxiake/article/details/51224569