Spring boot + Vue 实现 WebSocket

本贴最后更新于 1828 天前,其中的信息可能已经事过境迁

来,搞事情,pom 文件加上依赖

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>4.3.8.RELEASE</version> </dependency>

主要有三个文件

  1. WebSocketsConfig.java (WebSocket 配置文件)
  2. MyWebSocketInterceptor.java (可以看做是一个拦截器,beforeHandshake(websocket 握手之前), afterHandshake(握手之后))
  3. WebSocketPushHandler.java(Websocket 一些事件)

WebSocketsConfig.java

package sucblog.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; import org.springframework.web.socket.server.HandshakeInterceptor; import sucblog.websocket.MyWebSocketInterceptor; import sucblog.websocket.WebSocketPushHandler; @Configuration @EnableWebSocket public class WebSocketsConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(createWebSocketPushHandler(), "/webSocketServer") .addInterceptors(createHandshakeInterceptor()).setAllowedOrigins("*"); registry.addHandler(createWebSocketPushHandler(), "/sockjs/webSocketServer") .addInterceptors(createHandshakeInterceptor()).withSockJS(); } /** * 握手拦截器 * @return */ @Bean public HandshakeInterceptor createHandshakeInterceptor() { return new MyWebSocketInterceptor(); } @Bean public WebSocketHandler createWebSocketPushHandler() { return new WebSocketPushHandler(); } }

MyWebSocketInterceptor

package sucblog.websocket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.HandshakeInterceptor; import java.util.Map; public class MyWebSocketInterceptor implements HandshakeInterceptor { private Logger logger = LoggerFactory.getLogger(this.getClass()); /** * 在握手之前执行该方法,继续握手返回true ,中断握手返回false,通过map参数设置WebSocketSession的属性 * @param request * @param response * @param webSocketHandler * @param map * @return * @throws Exception */ @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception { logger.info("xxx用户建立连接..."); if (request instanceof ServletServerHttpRequest) { String userId = ((ServletServerHttpRequest) request).getServletRequest().getParameter("userId"); map.put("userId", userId); logger.info("用户唯一标识:" + userId); } return true; } /** * 在握手之后执行该方法,无论是否握手成功都致命了响应的状态码和响应头 * @param serverHttpRequest * @param serverHttpResponse * @param webSocketHandler * @param e */ @Override public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) { } }

WebSocketPushHandler

package sucblog.websocket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; public class WebSocketPushHandler extends TextWebSocketHandler { private Logger logger = LoggerFactory.getLogger(this.getClass()); private static final List<WebSocketSession> userList = new ArrayList<>(); /** * 用户进入 系统监听 * @param session * @throws Exception */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.info(session.getAttributes() + "用户进入系统。。。"); logger.info("用户信息:" + session.getAttributes()); Map<String, Object> map = session.getAttributes(); for (String key : map.keySet()) { logger.info("key:" + key + "and value: " + map.get(key)); } userList.add(session); sendMessagesToUsers(session); } /** * 处理用户请求 * @param session * @param message */ @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception{ logger.info("系统处理["+session.getAttributes().get("userId")+"]用户的请求信息==>" + message.getPayload()); sendMessageToUser((String) session.getAttributes().get("userId"), message); } /** * 用户退出后的处理 * @param session * @param status * @throws Exception */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { if (session.isOpen()) { session.close(); } userList.remove(session); logger.info("xxx用户退出系统"); } /** * 自定义函数 * 给所有在线用户发送消息 * @param */ public void sendMessagesToUsers(WebSocketSession session) { String msg = "欢迎'" + session.getAttributes().get("userId"); TextMessage message = new TextMessage(msg); for (WebSocketSession user : userList) { try { // isOpen() 在线就发送 if (user.isOpen()) { user.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); logger.error(e.getLocalizedMessage()); } } } public void sendMessageToUser(String userId, TextMessage message) { for (WebSocketSession user : userList) { try { if (user.isOpen()) { user.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); logger.error(e.getLocalizedMessage()); } } } }

前端代码

<template> <div style="margin: 150px auto; width: 500px;box-shadow: 0 0 20px #33333350; border-radius: 10px; padding: 20px;"> <h2>websocket学习学习</h2> <h3>学海无涯,回头是岸</h3> <div style="margin-top: 20px; text-align: left"> <input type="text" v-model="msg"> <button @click="websocketsend(msg)">发送</button> <div v-if="bmsg"> <ul> <li v-for="(item, i) in bmsg" :key="i"> <strong :class="{services:item.user==='服务器'}">{{item.user}}</strong> 回复时间:{{item.time}} <div> {{item.content}} </div> </li> </ul> </div> </div> </div> </template> <script> export default { name: 'KolOnlineChat', data() { return { websock: null, msg: null, bmsg: [], } }, mounted() { this.initWebSocket() }, destroyed() { this.websock.close() // 离开路由断开websocket连接 }, methods: { initWebSocket() { // 初始化websocket const wsuri = "wss://localhost:9999/webSocketServer?userId=parker" this.websock = new WebSocket(wsuri) this.websock.onmessage = this.websocketonmessage this.websock.onopen = this.websocketonopen this.websock.onerror = this.websocketonerror this.websock.onclose = this.websocketclose }, websocketonopen() { //连接建立之后执行send方法发送数据 // let actions = {'test': '12345'} // this.websocketsend(JSON.stringify(actions)) }, websocketonerror(){//连接建立失败重连 this.initWebSocket() }, websocketonmessage(e){ //数据接收 const redata = JSON.stringify(e.data) this.arrOpear(redata, 'services') }, websocketsend(Data){//数据发送 this.websock.send(Data) this.arrOpear(Data, 'localhost') }, websocketclose(e){ //关闭 console.log('断开连接',e) }, arrOpear(msg, type) { let _b = { content: msg, user: type === 'services'? '服务器' : '我', time: new Date().toLocaleTimeString() } this.bmsg.push(_b) } } } </script> <style scoped lang="less"> strong { color: #03be01; } strong.services { color: orangered; } </style>

运行截图:

image.png

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    949 引用 • 1460 回帖 • 1 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    268 引用 • 666 回帖
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 288 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    150 引用 • 257 回帖
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    86 引用 • 165 回帖
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    118 引用 • 54 回帖 • 3 关注
  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 680 关注
  • Access
    1 引用 • 3 回帖 • 2 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 649 关注
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 33 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 498 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 76 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    107 引用 • 153 回帖
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 29 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖 • 2 关注
  • OneNote
    1 引用 • 3 回帖
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    15 引用 • 7 回帖
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 62 关注
  • Follow
    4 引用 • 12 回帖 • 11 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 675 关注
  • 安全

    安全永远都不是一个小问题。

    203 引用 • 818 回帖 • 2 关注
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 589 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 85 关注
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    22 引用 • 148 回帖 • 16 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    199 引用 • 542 回帖 • 1 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 489 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    170 引用 • 1529 回帖