# SpringBoot-Websocket-Course **Repository Path**: e4glet/spring-boot-socket-course ## Basic Information - **Project Name**: SpringBoot-Websocket-Course - **Description**: SpringBoot集成socket开发与实践应用。 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-06-16 - **Last Updated**: 2023-06-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SpringBoot集成WebSocket应用教程 ### 课程介绍 SpringBoot集成WebSocket开发与实践应用。 ### 课程列表 - [基础练习](https://gitee.com/e4glet/spring-boot-socket-course/blob/master/README.md) - [项目练习之聊天室](https://gitee.com/e4glet/spring-boot-socket-course/blob/master/Course1.md) - [模拟真实应用实践](https://gitee.com/e4glet/spring-boot-socket-course/blob/master/Course2.md) ### 什么是WebSocket? 在TCP/IP协议栈的时候有关TCP Socket,它实际上是一种功能接口,通过这些接口就可以使用TCP/IP协议栈在传输层收发数据。 而WebSocket中,“Web”指的就是HTTP,“Socket”是在套接字调用,WebSocket就是运行在Web,也就是HTTP上的Socket通信规范,提供与TCP Socket类似的功能,使用它可以像TCP Socket一样调用下层协议栈,任意的收发数据。 ### WebSocket的特点 - WebSocket是一个真正的全双工的通信协议,支持双向通信,实时性更强。 - 更好的二进制支持。 - 服务发现方面,WebSocket没有使用TCP的“IP地址+端口号”,而是延用了HTTP的URI格式,但开头的协议名不是“http”,引入的是两个新的名字:“ws”和“wss”,分别表示明文和加密的WebSocket协议 - WebSocket的默认断开也选择了80和443,因为现在互联网上的防火墙屏蔽了绝大多数端口,只对HTTP的80、443端口“放行”,所以WebSocket就可以“伪装”成HTTP协议,比较容易的“穿透”防火墙,与服务器建立连接。 ### 什么是Websocket? ### 基础练习 #### SpringBoot整合WebSocket 1. 新建SpringBoot项目 ![输入图片说明](imgs/websocket01.png) ![输入图片说明](imgs/websocket02.png) 2. 在pom.xml配置文件内增加依赖 唯一与之前所学项目的区别就是新增了WebSocket依赖支持 ``` org.springframework.boot spring-boot-starter-websocket ``` 3. 编写WebSocket基础操作类(工具类) ``` package com.websocket.springbootwebsocketdemo.websocket; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; @ServerEndpoint("/websocket") @Component @Slf4j public class WebSocketBase { // 与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; // session集合,存放对应的session private static ConcurrentHashMap sessionPool = new ConcurrentHashMap<>(); // concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。 private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet<>(); /** * 建立连接成功 * @param session */ @OnOpen public void onOpen(Session session){ //建立连接 this.session=session; webSocketSet.add(this); log.info("【websocket消息】 有新的连接,总数{}",webSocketSet.size()); } /** * 连接关闭 */ @OnClose public void onClose(){ this.session=session; webSocketSet.remove(this); log.info("【websocket消息】 连接断开,总数{}",webSocketSet.size()); } /** * 接收客户端消息 * @param message */ @OnMessage public void onMessage(String message){ System.out.println("接收客户端发送过来的消息:"+message); //添加服务器响应 sendMessage("服务器接收到客户端消息,客户端消息内容为:"+message); } /** * 发送消息 * @param message */ public void sendMessage(String message){ log.info("【websocket消息】 发送消息:{}",message); for (WebSocketBase webSocket : webSocketSet) { try { webSocket.session.getBasicRemote().sendText(message); } catch (IOException e) { log.error("群发消息发生错误:" + e.getMessage(), e); } } } } ``` 4. 编写Websocket配置类 ``` package com.websocket.springbootwebsocketdemo.confg; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * WebSocket 配置类 * 开启websocket支持 */ @Configuration @ConditionalOnWebApplication public class WebSocketConfig { /** * 这个bean的注册,用于扫描带有@ServerEndpoint的注解成为websocket,如果你使用外置的tomcat就不需要该配置文件 */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } ``` #### 新建vue2项目 WebSocket前端基础知识点及概念: https://www.runoob.com/html/html5-websocket.html 1. 添加测试页面组件 ``` ``` 2. 新增路由地址 ``` { path: '/websocket', name: 'websocket', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import('../views/WebSocket.vue') }, ``` 3. 修改vue.config.js ``` const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, // 公共路径(必须有的) publicPath: "/", // 输出文件目录 outputDir: "dist", // 静态资源存放的文件夹(相对于ouputDir) assetsDir: "assets", // eslint-loader 是否在保存的时候检查(果断不用,这玩意儿我都没装) lintOnSave: false, // 我用的only,打包后小些 runtimeCompiler: false, productionSourceMap: true, // 不需要生产环境的设置false可以减小dist文件大小,加速构建 devServer: { open: true, // npm run serve后自动打开页面 host: '0.0.0.0', // 匹配本机IP地址(默认是0.0.0.0) port: 8089, // 开发服务器运行端口号 proxy: null, // history模式下的url会请求到服务器端,但是服务器端并没有这一个资源文件,就会返回404,所以需要配置这一项 }, }) ``` 4. 分别运行SpringBoot项目和vue项目进行测试 ![输入图片说明](imgs/websocket04.png) #### 如何接收服务器端消息 1. Springboot后端在接收客户端方法里,将服务器发送消息写入 ``` /** * 接收客户端消息 * @param message */ @OnMessage public void onMessage(String message){ System.out.println("接收客户端发送过来的消息:"+message); //下面这行就是服务器向客户端发送消息的方法 sendMessage("服务器接收到信息!over!"); } ``` 2. 完善vue客户端代码 ``` ``` 3. 运行测试 ![输入图片说明](imgs/websocket05.png) ### 作者 1. e4glet