目录结构
    image.png
    第一步:万事第一步导包

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-websocket</artifactId>
    4. </dependency>

    第二步:创建启动配置类WebsocketConfig

    1. package com.mhy.chat.config;
    2. //⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    3. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡖⠒⠒⠤⢄⠀⠀
    4. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀⠀⡼⠀⠀⠀⠀ ⠀
    5. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢶⣲⡴⣗⣲⡦⢤⡏⠀⠀⠀⠀⠀
    6. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠋⠉⠉⠓⠛⠿⢷⣶⣦⠀⠀⠀
    7. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠘⡇⠀⠀⠀⠀
    8. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⠀⠀⠀⢰⠇⠀⠀⠀⠀
    9. // ⠀⠀⠀⠀⠀⠀⠀⠀⡴⠊⠉⠳⡄⠀⢀⣀⣀⡀⠀⣸⠀⠀⠀⠀⠀
    10. // ⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠰⠆⣿⡞⠉⠀⠀⠉⠲⡏⠀⠀⠀⠀⠀
    11. // ⠀⠀⠀⠀⠀⠀⠀⠈⢧⡀⣀⡴⠛⡇⠀:⠃⠀⠀⡗⠀⠀⠀⠀⠀
    12. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣱⠃⡴⠙⠢⠤⣀⠤⡾⠁⠀⠀⠀⠀⠀
    13. // ⠀⠀⠀⠀⠀⠀⠀⠀⢀⡇⣇⡼⠁⠀⠀⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀
    14. // ⠀⠀⠀⠀⠀⠀⠀⠀⣸⢠⣉⣀⡴⠙⠀⠀⠀⣼⠀⠀⠀⠀⠀⠀⠀
    15. // ⠀⠀⠀⠀⠀⠀⠀⠀⡏⠀⠈⠁⠀⠀⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
    16. // ⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠀⠀⠀⠀⠀⠀⡼⠀⠀⠀⠀⠀⠀⠀⠀
    17. // ⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⣰⠃⠀⠀⠀⠀⠀⠀⠀⠀
    18. // ⠀⠀⠀⠀⠀⣀⠤⠚⣶⡀⢠⠄⡰⠃⣠⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀
    19. // ⠀⢀⣠⠔⣋⣷⣠⡞⠀⠉⠙⠛⠋⢩⡀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀
    20. // ⠀⡏⢴⠋⠁⠀⣸⠁⠀⠀⠀⠀⠀⠀⣹⢦⣶⡛⠳⣄⠀⠀⠀⠀⠀
    21. // ⠀⠙⣌⠳ 小马无忧 ⡏⠀⠀⠈⠳⡌⣦⠀⠀⠀
    22. // ⠀⠀⠈⢳⣈⣻ ⢰⣇⣀⡠⠴⢊⡡⠋⠀⠀⠀⠀
    23. // ⠀⠀⠀⠀⠳⢿⡇⠀⠀⠀⠀⠀⠀⢸⣻⣶⡶⠊⠁⠀⠀
    24. // ⠀⠀⠀⠀⠀⢠⠟⠙⠓⠒⠒⠒⠒⢾⡛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀
    25. // ⠀⠀⠀⠀⣠⠏⠀⣸⠏⠉⠉⠳⣄⠀⠙⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀
    26. // ⠀⠀⠀⡰⠃⠀⡴⠃⠀⠀⠀⠀⠈⢦⡀⠈⠳⡄⠀⠀⠀⠀⠀⠀⠀
    27. // ⠀⠀⣸⠳⣤⠎⠀⠀⠀⠀⠀⠀⠀⠀⠙⢄⡤⢯⡀⠀⠀⠀⠀⠀⠀
    28. // ⠀⠐⡇⠸⡅⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⡆⢳⠀⠀⠀⠀⠀⠀
    29. // ⠀⠀⠹⡄⠹⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣇⠸⡆⠀⠀⠀⠀⠀
    30. // ⠀⠀⠀⠹⡄⢳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡀⣧⠀⠀⠀⠀⠀
    31. // ⠀⠀⠀⠀⢹⡤⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣷⠚⣆⠀⠀⠀⠀
    32. // ⠀⠀⠀⡠⠊⠉⠉⢹⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡎⠉⠀⠙⢦⡀⠀
    33. // ⠀⠀⠾⠤⠤⠶⠒⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠒⠲⠤⠽⠀
    34. import org.springframework.context.annotation.Bean;
    35. import org.springframework.context.annotation.Configuration;
    36. import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    37. @Configuration
    38. public class WebsocketConfig {
    39. @Bean
    40. public ServerEndpointExporter createSEE(){
    41. return new ServerEndpointExporter();
    42. }
    43. }

    第三步:创建服务类chatserver

    1. package com.mhy.chat;
    2. import org.springframework.context.annotation.Scope;
    3. import org.springframework.stereotype.Component;
    4. import sun.plugin2.os.windows.SECURITY_ATTRIBUTES;
    5. import javax.websocket.*;
    6. import javax.websocket.server.PathParam;
    7. import javax.websocket.server.ServerEndpoint;
    8. import java.io.IOException;
    9. import java.util.concurrent.ConcurrentHashMap;
    10. //实例化对象交由spring管理(控制反转)
    11. @Component
    12. //多例模式:因为每一个用户就是一个单独
    13. @Scope(scopeName = "prototype")
    14. @ServerEndpoint("/chat/server/{nickname}")
    15. public class ChatServer {
    16. //用户昵称
    17. private String nickname;
    18. //会话对象
    19. private Session session;
    20. //记录当前用户
    21. public static ConcurrentHashMap<String, Session> users = new ConcurrentHashMap<>();//记录当前用户
    22. //连接-服务器
    23. @OnOpen
    24. public void open(@PathParam("nickname") String name, Session session) {
    25. if (users.contains(name)) {
    26. sendMsg(session, "你的昵称已被占用");
    27. } else {
    28. this.nickname = name;
    29. this.session = session;
    30. users.put(name, session);
    31. sendMoreMsg(name + "进入聊天室");
    32. }
    33. }
    34. //监听消息 接受消息
    35. @OnMessage
    36. public void message(String msg, Session session) {
    37. System.err.println("服务端接收" + msg);
    38. sendMsg(session, "已收到!over");
    39. sendMoreMsg(nickname+"-说:"+msg);
    40. }
    41. private static void sendMsg(Session session, String msg) {
    42. try {
    43. session.getBasicRemote().sendText(msg);
    44. } catch (IOException e) {
    45. e.printStackTrace();
    46. }
    47. }
    48. @OnError //异常监听,只要出错误
    49. public void error(Throwable throwable){
    50. System.err.println("出错了");
    51. }
    52. @OnClose //监听关闭
    53. public void close(Session session){
    54. users.remove(nickname);//移除
    55. sendMoreMsg("让我们掌声欢送 "+nickname+" 的离开!");
    56. }
    57. private static void sendMoreMsg(String msg) {
    58. try {
    59. for (String s : users.keySet()) {
    60. users.get(s).getBasicRemote().sendText(msg);
    61. }
    62. } catch (IOException e) {
    63. e.printStackTrace();
    64. }
    65. }
    66. //推送消息
    67. public static boolean pushMsg(String msg){
    68. sendMoreMsg(msg);
    69. return true;
    70. }
    71. }

    第四步:开启项目进行测试
    先进行线上测试:http://www.jsons.cn/websocket/
    输入链接:ws:localhost:9999/chat/server/马辉远
    测试截图:
    image.png
    image.png
    第五步:测试成功之后可以写一个小接口MessageController

    1. package com.mhy.chat.api;
    2. import com.mhy.chat.ChatServer;
    3. import org.springframework.web.bind.annotation.GetMapping;
    4. import org.springframework.web.bind.annotation.RequestMapping;
    5. import org.springframework.web.bind.annotation.RestController;
    6. @RestController
    7. @RequestMapping("/api/msg/")
    8. public class MessageController {
    9. @GetMapping("tuisong.do")
    10. public String msg(String msg){
    11. ChatServer.pushMsg(msg);
    12. return "消息推送成功!";
    13. }
    14. }

    第六步书写vue页面:

    1. <template>
    2. <div>
    3. <!-- 1.连接 -->
    4. <div>
    5. <van-cell-group inset>
    6. <van-field
    7. v-model="nickname"
    8. center
    9. label-width="50px"
    10. clearable
    11. label="昵称"
    12. placeholder="请输入昵称"
    13. >
    14. <template #button>
    15. <van-button size="small" type="primary" @click="joinRoom()">连接</van-button>
    16. <van-button size="small" style="margin-left: 10px;" type="info" @click="exitRoom()">退出</van-button>
    17. </template>
    18. </van-field>
    19. </van-cell-group>
    20. </div>
    21. <!-- 2.聊天信息 -->
    22. <div>
    23. <van-cell v-for="item in msgs" :key="item" :title="item" />
    24. </div>
    25. <!-- 3.发送消息 -->
    26. <div style="position: absolute; bottom: 37px;width: 100%;">
    27. <van-cell-group inset>
    28. <van-field
    29. v-model="msg"
    30. center
    31. clearable
    32. placeholder="请输入聊天信息"
    33. >
    34. <template #button>
    35. <van-button size="small" type="primary" @click="sendMsg()">发送</van-button>
    36. </template>
    37. </van-field>
    38. </van-cell-group>
    39. </div>
    40. </div>
    41. </template>
    42. <script>
    43. export default{
    44. data(){
    45. return{
    46. nickname:"",
    47. msg:"",
    48. msgs:[
    49. "测试01"
    50. ],
    51. ws:{}
    52. }
    53. },
    54. methods:{
    55. joinRoom(){
    56. if ('WebSocket' in window){
    57. //完成实例化
    58. this.ws = new WebSocket("ws://localhost:9999/chat/server/"+this.nickname);
    59. //监听消息接收
    60. this.ws.onmessage = (res=>{
    61. console.log("数据已接收...",res.data);
    62. this.msgs.push(res.data);
    63. });
    64. //连接服务器
    65. this.ws.onopen=(res=>{
    66. this.msgs.push("加入成功");
    67. });
    68. }
    69. },
    70. exitRoom(){
    71. console.log("退出");
    72. this.ws.close();
    73. this.msgs.push("退出聊天室");
    74. this.nickname="";
    75. },
    76. sendMsg(){//发送聊天消息
    77. this.ws.send(this.msg);//发送消息
    78. this.msgs.push("我说:"+this.msg);
    79. this.msg="";
    80. }
    81. }
    82. }
    83. </script>
    84. <style>
    85. </style>

    最后:运行测试
    image.png