SpringBoot使用websocket实现简单聊天室
1.实现代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
@Configuration
public class WebsocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
@Slf4j
@Component
@ServerEndpoint(value = "/ws/chat")
public class ChatSocketServer {
public static final AtomicInteger onlineCount = new AtomicInteger(0);
public static Map<String, Session> clients = new ConcurrentHashMap<>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
String username=session.getRequestParameterMap().get("username").get(0);
log.info("有新的客户端上线 sessionid={} username={}", session.getId(),username);
clients.put(username,session);
int cnt = onlineCount.incrementAndGet(); // 在线数加1
log.info("有连接加入,当前在线人数为:{}", cnt);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
clients.remove(session);
int cnt = onlineCount.decrementAndGet();
log.info("在线人数为:{}", cnt);
}
/**
* 出现错误
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误:{},Session ID: {}",error.getMessage(),session.getId());
error.printStackTrace();
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("消息:{}",message);
//SendMessage(session, "收到消息,消息内容:"+message);
}
/**
* 发送消息,username为空就群发
*/
public static void SendMessage(Message message) throws IOException {
//username为空就群发
if(StringUtils.isBlank(message.getTo())){
for (Map.Entry<String,Session> entry: clients.entrySet()) {
Session session=entry.getValue();
if(session.isOpen()){
session.getBasicRemote().sendText(JSON.toJSONString(message));
}
}
}else{
for (Map.Entry<String,Session> entry: clients.entrySet()) {
if(entry.getKey().equals(message.getTo())){
Session session=entry.getValue();
if(session!=null && session.isOpen()){
session.getBasicRemote().sendText(JSON.toJSONString(message));
}else{
log.warn("没有找到你指定用户:{}",message.getTo());
}
break;
}
}
}
}
}
@Controller
public class ChatController {
@GetMapping("/")
public String index(){
return "chat";
}
@GetMapping("/chat/send")
@ResponseBody
public AjaxResult send(String from,String to,String message) throws IOException {
ChatSocketServer.SendMessage(new Message(from,to,message,new Date()));
return AjaxResult.success();
}
//在线用户列表
@GetMapping("/getOnlineUser")
@ResponseBody
public AjaxResult getOnlineUser() {
return AjaxResult.success(ChatSocketServer.clients.keySet());
}
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Message {
private String from;
private String to;
private String message;
private Date time;
}
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>网页聊天室</title>
<style type="text/css">
.chatdiv{width: 800px;height: 300px;padding: 10px;margin: 10px;border: #444 solid 1px;}
.myshuo{text-align: right;border-bottom: #ccc solid 1px;padding: 5px 0;color: green;width: 100%}
.othershuo{text-align: left;border-bottom: #ccc solid 1px;padding: 5px 0;color: dodgerblue;width: 100%}
.xitongshuo{text-align: center;border-bottom: #ccc solid 1px;padding: 5px 0;color: red;font-weight: bold;width: 100%}
</style>
</head>
<body>
<div id="loginpage" style="display: block">
<h3>用户登陆</h3>
输入用户名:<input type="text" id="username"><input type="button" onclick="login()" value="登陆">
</div>
<div id="chatpage" style="display: none">
<div class="chatdiv" id="chatdiv"></div>
<div>
<select id="to" multiple="multiple" size="5">
</select>
<input type="button" onclick="getOnlineUser()" value="刷新当前在线用户">
<input type="text" id="text"><input type="button" onclick="sendMessage()" value="发送">
</div>
</div>
<script src="http://apps.bdimg.com/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
var socket;
var myusername="";
function getOnlineUser(){
$.get("/getOnlineUser",{},function(result){
$("#to").empty();
$("#to").append($("<option>").val("").text("全部"));
for(var i=0;i<result.data.length;i++){
$("#to").append($("<option>").val(result.data[i]).text(result.data[i]));
}
},'json');
}
function sendMessage(){
var text=$("#text").val();
if(text==''){
alert('消息内容不能为空');
return;
}
var to=$("#to").val()[0];
if(to!=''){
$("#chatdiv").append("<div class='myshuo'>我说:"+text+"</div>");
}
$.get("/chat/send",{from:myusername,to:to,message:text},function(result){
console.info(result);
$("#text").val("");
},'json');
}
function login(){
var username=$("#username").val();
if(username==''){
alert('用户不能为空');
return;
}
myusername=username;
if (typeof (WebSocket) == "undefined") {
console.log("遗憾:您的浏览器不支持WebSocket");
} else {
console.log("恭喜:您的浏览器支持WebSocket");
//实现化WebSocket对象
//指定要连接的服务器地址与端口建立连接
//注意ws、wss使用不同的端口。我使用自签名的证书测试,无法使用wss,浏览器打开WebSocket时报错
//ws对应http、wss对应https。
socket = new WebSocket("ws://localhost:8082/ws/chat?username="+username);
//连接打开事件
socket.onopen = function() {
console.log("Socket 已打开");
//socket.send("消息发送测试(From Client)");
$("#loginpage").hide();
$("#chatpage").show();
getOnlineUser();
};
//收到消息事件
socket.onmessage = function(msg) {
console.log(msg.data);
var message=JSON.parse(msg.data);
if(message.to==''){
$("#chatdiv").append("<div class='xitongshuo'>【管理员】"+message.from+"说:"+message.message+"</div>");
}else{
$("#chatdiv").append("<div class='othershuo'>"+message.from+"说:"+message.message+"</div>");
}
};
//连接关闭事件
socket.onclose = function() {
console.log("Socket已关闭");
};
//发生了错误事件
socket.onerror = function() {
alert("Socket发生了错误");
}
//窗口关闭时,关闭连接
window.unload=function() {
socket.close();
};
}
}
</script>
</body>
</html>
测试效果截图: