一、前端
1.本地开发环境
//后端路径和用户Id
wsUrl='ws://localhost:8080/websocket/message/'+userId
const websocketState = reactive({
socket: null,
url: wsUrl,
})
//连接方法
function connect () {
websocketState.socket = new WebSocket(websocketState.url)
//连接
websocketState.socket.onopen = () => {
console.log('WebSocket已连接')
}
//关闭连接
websocketState.socket.onclose = () => {
}
//接收消息
websocketState.socket.onmessage = (event) => {
console.log(`收到消息:${event.data}`)
}
}
//连接
connect()
2.线上环境
- 192.168.237.160 线上访问的是服务器nginx的端口,默认是80端口。如果这里加入后端端口192.168.237.160:8080 它不会过nginx的。
- cloud-boot: 为后端代理字段。
- /websocket/message 为后端路径。
- userId: 连接的用户Id(唯一)。
wsUrl='ws://192.168.237.160/cloud-boot/websocket/message/'+userId
3.VITE配置
.env.development 开发环境
# 页面标题
VITE_APP_TITLE = cloud
# 开发环境配置
VITE_APP_ENV = 'development'
# 开发环境
VITE_APP_BASE_API = '/dev-api'
VITE_APP_URL = 'http://localhost:8080'
.env.production 生产环境
# 页面标题
VITE_APP_TITLE = cloud
# 生产环境配置
VITE_APP_ENV = 'production'
# 生产环境
VITE_APP_BASE_API = '/cloud-chat'
VITE_APP_URL = 'http://192.168.237.160'
前端url(开发生产两用)
var appURL = import.meta.env.VITE_APP_URL.replace("http", "ws").replace("https", "ws")
var baseURL = import.meta.env.VITE_APP_BASE_API
var appEnv =import.meta.env.VITE_APP_ENV
var wsUrl=ref('')
if (appEnv==='production'){
wsUrl=appURL+baseURL+'/websocket/message/'+user.userId
}else if (appEnv==='development'){
wsUrl=appURL+'/websocket/message/'+user.userId
}
二、后端
1.依赖类
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.配置类
@Configuration
@EnableWebSocket
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter()
{
return new ServerEndpointExporter();
}
}
3.消息处理类
@Component
@Slf4j
@ServerEndpoint("/websocket/message/{uid}")
public class WebSocketServer {
/**
* 存放所有在线的客户端
*/
private static Map<String, Session> onlineSessionClientMap = new ConcurrentHashMap<>();
/**
* 连接uid
*/
private String uid;
/**
* 连接会话
*/
private Session session;
/**
* 连接建立成功调用的方法。
*/
@OnOpen
public void onOpen(@PathParam("sid") String uid, Session session) {
onlineSessionClientMap.put(uid, session);
}
/**
* 连接关闭方法
*/
@OnClose
public void onClose(@PathParam("uid") String uid, Session session) {
onlineSessionClientMap.remove(uid);
}
/**
* 收到客户端消息后调用的方法。
*/
@OnMessage
public void onMessage(String message, Session session) {
onlineSessionClientMap.forEach((onlineSid, toSession)->{
toSession.getAsyncRemote().sendText(message);
});
}
/**
* 发生错误调用的方法
*/
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
/**
* 做提醒时指定用户发送消息
*/
private void sendToOne(String toSid, String message) {
Session toSession = onlineSessionClientMap.get(toSid);
if (toSession == null) {
return;
}
toSession.getAsyncRemote().sendText(message);
}
}
三、Nginx配置
关键配置:
- 在http{}块下添加:
map $http_upgrade $connection_upgrade { default upgrade; '' close; }
在location /cloud-chat {}块中添加
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
nginx文件如下:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
client_max_body_size 100m;
server {
listen 80;
server_name localhost;
location / {
root /usr/local/nginx/html;
#try_files $uri $uri/ /cloud/dist/index.html;
index index.html index.htm;
}
location /cloud{
alias /usr/local/nginx/html/cloud/dist;
try_files $uri $uri/ /dist/index.html;
index index.html index.htm;
}
location /cloud-chat{
proxy_pass http:localhost:8080;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}