目录结构
第一步:万事第一步导包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
第二步:创建启动配置类WebsocketConfig
package com.mhy.chat.config;
//⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡖⠒⠒⠤⢄⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀⠀⡼⠀⠀⠀⠀ ⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢶⣲⡴⣗⣲⡦⢤⡏⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠋⠉⠉⠓⠛⠿⢷⣶⣦⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠘⡇⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⠀⠀⠀⢰⠇⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⡴⠊⠉⠳⡄⠀⢀⣀⣀⡀⠀⣸⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠰⠆⣿⡞⠉⠀⠀⠉⠲⡏⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠈⢧⡀⣀⡴⠛⡇⠀:⠃⠀⠀⡗⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣱⠃⡴⠙⠢⠤⣀⠤⡾⠁⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⢀⡇⣇⡼⠁⠀⠀⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⣸⢠⣉⣀⡴⠙⠀⠀⠀⣼⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⡏⠀⠈⠁⠀⠀⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠀⠀⠀⠀⠀⠀⡼⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⣰⠃⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⣀⠤⠚⣶⡀⢠⠄⡰⠃⣠⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⢀⣠⠔⣋⣷⣠⡞⠀⠉⠙⠛⠋⢩⡀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀
// ⠀⡏⢴⠋⠁⠀⣸⠁⠀⠀⠀⠀⠀⠀⣹⢦⣶⡛⠳⣄⠀⠀⠀⠀⠀
// ⠀⠙⣌⠳ 小马无忧 ⡏⠀⠀⠈⠳⡌⣦⠀⠀⠀
// ⠀⠀⠈⢳⣈⣻ ⢰⣇⣀⡠⠴⢊⡡⠋⠀⠀⠀⠀
// ⠀⠀⠀⠀⠳⢿⡇⠀⠀⠀⠀⠀⠀⢸⣻⣶⡶⠊⠁⠀⠀
// ⠀⠀⠀⠀⠀⢠⠟⠙⠓⠒⠒⠒⠒⢾⡛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⣠⠏⠀⣸⠏⠉⠉⠳⣄⠀⠙⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⡰⠃⠀⡴⠃⠀⠀⠀⠀⠈⢦⡀⠈⠳⡄⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⣸⠳⣤⠎⠀⠀⠀⠀⠀⠀⠀⠀⠙⢄⡤⢯⡀⠀⠀⠀⠀⠀⠀
// ⠀⠐⡇⠸⡅⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⡆⢳⠀⠀⠀⠀⠀⠀
// ⠀⠀⠹⡄⠹⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣇⠸⡆⠀⠀⠀⠀⠀
// ⠀⠀⠀⠹⡄⢳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡀⣧⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⢹⡤⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣷⠚⣆⠀⠀⠀⠀
// ⠀⠀⠀⡠⠊⠉⠉⢹⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡎⠉⠀⠙⢦⡀⠀
// ⠀⠀⠾⠤⠤⠶⠒⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠒⠲⠤⠽⠀
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebsocketConfig {
@Bean
public ServerEndpointExporter createSEE(){
return new ServerEndpointExporter();
}
}
第三步:创建服务类chatserver
package com.mhy.chat;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import sun.plugin2.os.windows.SECURITY_ATTRIBUTES;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
//实例化对象交由spring管理(控制反转)
@Component
//多例模式:因为每一个用户就是一个单独
@Scope(scopeName = "prototype")
@ServerEndpoint("/chat/server/{nickname}")
public class ChatServer {
//用户昵称
private String nickname;
//会话对象
private Session session;
//记录当前用户
public static ConcurrentHashMap<String, Session> users = new ConcurrentHashMap<>();//记录当前用户
//连接-服务器
@OnOpen
public void open(@PathParam("nickname") String name, Session session) {
if (users.contains(name)) {
sendMsg(session, "你的昵称已被占用");
} else {
this.nickname = name;
this.session = session;
users.put(name, session);
sendMoreMsg(name + "进入聊天室");
}
}
//监听消息 接受消息
@OnMessage
public void message(String msg, Session session) {
System.err.println("服务端接收" + msg);
sendMsg(session, "已收到!over");
sendMoreMsg(nickname+"-说:"+msg);
}
private static void sendMsg(Session session, String msg) {
try {
session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
@OnError //异常监听,只要出错误
public void error(Throwable throwable){
System.err.println("出错了");
}
@OnClose //监听关闭
public void close(Session session){
users.remove(nickname);//移除
sendMoreMsg("让我们掌声欢送 "+nickname+" 的离开!");
}
private static void sendMoreMsg(String msg) {
try {
for (String s : users.keySet()) {
users.get(s).getBasicRemote().sendText(msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//推送消息
public static boolean pushMsg(String msg){
sendMoreMsg(msg);
return true;
}
}
第四步:开启项目进行测试
先进行线上测试:http://www.jsons.cn/websocket/
输入链接:ws:localhost:9999/chat/server/马辉远
测试截图:
第五步:测试成功之后可以写一个小接口MessageController
package com.mhy.chat.api;
import com.mhy.chat.ChatServer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/msg/")
public class MessageController {
@GetMapping("tuisong.do")
public String msg(String msg){
ChatServer.pushMsg(msg);
return "消息推送成功!";
}
}
第六步书写vue页面:
<template>
<div>
<!-- 1.连接 -->
<div>
<van-cell-group inset>
<van-field
v-model="nickname"
center
label-width="50px"
clearable
label="昵称"
placeholder="请输入昵称"
>
<template #button>
<van-button size="small" type="primary" @click="joinRoom()">连接</van-button>
<van-button size="small" style="margin-left: 10px;" type="info" @click="exitRoom()">退出</van-button>
</template>
</van-field>
</van-cell-group>
</div>
<!-- 2.聊天信息 -->
<div>
<van-cell v-for="item in msgs" :key="item" :title="item" />
</div>
<!-- 3.发送消息 -->
<div style="position: absolute; bottom: 37px;width: 100%;">
<van-cell-group inset>
<van-field
v-model="msg"
center
clearable
placeholder="请输入聊天信息"
>
<template #button>
<van-button size="small" type="primary" @click="sendMsg()">发送</van-button>
</template>
</van-field>
</van-cell-group>
</div>
</div>
</template>
<script>
export default{
data(){
return{
nickname:"",
msg:"",
msgs:[
"测试01"
],
ws:{}
}
},
methods:{
joinRoom(){
if ('WebSocket' in window){
//完成实例化
this.ws = new WebSocket("ws://localhost:9999/chat/server/"+this.nickname);
//监听消息接收
this.ws.onmessage = (res=>{
console.log("数据已接收...",res.data);
this.msgs.push(res.data);
});
//连接服务器
this.ws.onopen=(res=>{
this.msgs.push("加入成功");
});
}
},
exitRoom(){
console.log("退出");
this.ws.close();
this.msgs.push("退出聊天室");
this.nickname="";
},
sendMsg(){//发送聊天消息
this.ws.send(this.msg);//发送消息
this.msgs.push("我说:"+this.msg);
this.msg="";
}
}
}
</script>
<style>
</style>
最后:运行测试