# 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项目


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项目进行测试

#### 如何接收服务器端消息
1. Springboot后端在接收客户端方法里,将服务器发送消息写入
```
/**
* 接收客户端消息
* @param message
*/
@OnMessage
public void onMessage(String message){
System.out.println("接收客户端发送过来的消息:"+message);
//下面这行就是服务器向客户端发送消息的方法
sendMessage("服务器接收到信息!over!");
}
```
2. 完善vue客户端代码
```
```
3. 运行测试

### 作者
1. e4glet