Springboot工程中使用websocket通讯

483人浏览 / 0人评论 / 添加收藏

一,搭建环境
创建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: 18080

二,编写代码
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:18080/#/websocket每个人设置的端口可能不同。

访问localhost:18080/sendall/你好,此时在第一个页面会实时显示出内容。

也可以访问 localhost:18080/sendone/zhangsan/你好张三 给指定用户发送,这里的zhangsan是在utils/websocket.js中设置的,实际开发中应该是使用token从后端获取得到用户信息保存到本地再去连接的。

经验证后实测有效。

全部评论