一,搭建环境
创建springboot项目,加入相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
在application.yml里添加配置信息
server:
port: 8443
二,编写代码
1.添加配置文件
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
@EnableWebSocket
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpoint() {
return new ServerEndpointExporter();
}
}
2.添加controller层
该类用于连接websocket
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.CopyOnWriteArrayList;
@ServerEndpoint("/websocket/{token}")
@Component
public class WebSocketController {
private static int onlineCount=0;//在线人数
private static CopyOnWriteArrayList<WebSocketController> webSocketSet=new CopyOnWriteArrayList<WebSocketController>();//在线用户集合
private Session session;//与某个客户端的连接会话
private String currentUser;
@OnOpen
public void onOpen(@PathParam("token") String token, Session session){
this.currentUser = token;
this.session=session;
webSocketSet.add(this);//加入set中
addOnlineCount();
System.out.println("有新连接加入!当前在线人数为"+getOnlineCount());
allCurrentOnline();
}
@OnClose
public void onClose(){
webSocketSet.remove(this);
subOnlineCount();
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
allCurrentOnline();
}
@OnMessage
public void onMessage(String message,Session session){
System.out.println("来自客户端的消息:"+message);
for (WebSocketController item:webSocketSet){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
@OnError
public void onError(Session session, Throwable throwable){
System.out.println("发生错误!");
throwable.printStackTrace();
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 获取当前所有在线用户名
*/
public static void allCurrentOnline(){
for (WebSocketController item : webSocketSet) {
System.out.println(item.currentUser);
}
}
/**
* 发送给指定用户
*/
public static void sendMessageTo(String message,String token) throws IOException {
for (WebSocketController item : webSocketSet) {
if(item.currentUser.equals(token)){
item.session.getBasicRemote().sendText(message);
}
}
}
/**
* 群发自定义消息
*/
public static void sendInfo(String message) throws IOException {
System.out.println(message);
for (WebSocketController item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
continue;
}
}
}
public static synchronized int getOnlineCount(){
return onlineCount;
}
public static synchronized void addOnlineCount(){
WebSocketController.onlineCount++;
}
public static synchronized void subOnlineCount(){
WebSocketController.onlineCount--;
}
}
该类用于服务端给客户端发送消息
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
public class HelloController {
//给指定用户发
@GetMapping("/sendone/{message}/{token}")
public String sendmessage(@PathVariable("message") String message,@PathVariable("token") String token) throws IOException {
WebSocketController.sendMessageTo(message,token);
return "ok";
}
//这个可以后台群发,所有用户都能看到
@GetMapping("/sendall/{message}")
public String sendmessageall(@PathVariable("message") String message) throws IOException {
WebSocketController.sendInfo(message);
return "ok";
}
}
三,创建前端页面
创建空白页面,这个页面是模拟用户操作的任何页面,我的主要目的是实现服务端给客户端实时推送消息,如要实现聊天功能,可以在本页面添加功能
<template>
</template>
<script>
export default {
name: "websocket"
}
</script>
<style scoped>
</style>
1.使用vuex,elementui
使用vuex主要是模拟在实际项目中的使用
npm install vuex --save
npm i element-ui -S
src目录下添加store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state:{
websocketMessage:''
},
mutations: {
setWebsocketMessage (state,message) {
state.websocketMessage=message
}
}
})
export default store
src目录下创建utils/websocket.js
import store from "../store";
import {Message} from 'element-ui'
let url = 'ws://localhost:8443/websocket/'
//这里的zhangsan写死了,实际开发中应该是使用token从后端获取得到用户信息保存到本地再去连接的
let websocket=new WebSocket(url+'zhangsan');
export const connectWebsocket=()=>{
websocket.onopen = function () {
console.log('webSocket连接创建。。。');
}
websocket.onclose = function () {
console.log(this.message + "断开了连接")
}
websocket.onmessage = function (event) {
把传过来的消息存储在store中可以在页面中使用
store.commit('setWebsocketMessage',event.data)
//这里使用elementui直接提示后端发过来的消息
Message.success('消息提示:'+event.data)
console.log("接收到信息:" + event.data)
}
websocket.onerror = function (event) {
console.log('webSocket连接异常。。。');
}
}
export const closetWebsocket=()=>{
websocket.close()
}
2.修改App.vue
import {closetWebsocket,connectWebsocket} from './utils/websocket'
export default {
name: 'App',
beforeCreate() {
connectWebsocket()
},
created() {
window.onbeforeunload = function () {
closetWebsocket()
}
}
}
3.添加路由
{
path: '/websocket',
name: 'websocket',
component: websocket
}
四,测试
启动前后端项目
访问localhost:8080/#/websocket每个人设置的端口可能不同
访问localhost:8443/sendall/你好,此时在第一个页面会实时显示出内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G9xzxWMC-1638683410858)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20211205132653358.png)]
也可以访问 localhost:8443/sendone/zhangsan/你好张三 给指定用户发送,这里的zhangsan是在utils/websocket.js中设置的,实际开发中应该是使用token从后端获取得到用户信息保存到本地再去连接的
本文章只是做个记录
|