用 Spring boot 实现 web socket 应用

本贴最后更新于 1812 天前,其中的信息可能已经时异事殊

1、 首先通过 idea 创建一个 Springboot 项目,具体操作步骤如下:

image.png

image.png

点击 next

image.png

点击 next

image.png

按照上图操作

image.png

点击 finish 完成项目
2、 创建好的项目的目录结构

image.png

3、 创建如下的目录结构

image.png

4、 先定义一个常量类备用,代码如下:

package com.example.webscoket.consts;


/**
 * @program: easy
 * @description: WebScoket常量配置
 * @author: 王震
 * @create: 2019-05-06 10:11
 **/
public class GlobalConsts {
    /**
     * @Description Stomp的端点
     **/
    public static final String ENDPOINT = "/gs-guide-websocket";
    /**
     * @Description 收发消息url前缀
     **/
    public static final String APP_PREFIX = "/app";
    /**
     * @Description 接收消息地址
     **/
    public static final String RECEIVE_MAPPING = "/receive";

    /**
     * @Description 点对点消息推送地址前缀
     **/
    public static final String P2PPUSHBASEPATH = "/user";
    /**
     * @Description 点对点消息推送地址后缀,最后的地址为/user/用户识别码/msg
     **/
    public static final String P2PPUSHPATH = "/msg";
}

代码结构如下:

image.png

5、 创建配置类

package com.example.webscoket.config;


import com.example.webscoket.consts.GlobalConsts;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
* @Author 王震
* @Description Webscoket配置类
* @Date 21:33 2019/5/6
**/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
  @Override
  public void configureMessageBroker(MessageBrokerRegistry config) {
      /**
       * 配置消息代理
       * 启动简单Broker,消息的发送的地址符合配置的前缀来的消息才发送到这个broker
       */
      config.enableSimpleBroker(GlobalConsts.P2PPUSHBASEPATH);
      config.setUserDestinationPrefix(GlobalConsts.P2PPUSHBASEPATH);
      config.setApplicationDestinationPrefixes(GlobalConsts.APP_PREFIX);
  }

  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
      /**
       * 注册 Stomp的端点
       * addEndpoint:添加STOMP协议的端点。这个HTTP URL是供WebSocket或SockJS客户端访问的地址
       * setAllowedOrigins("*") 允许跨域
       * withSockJS:指定端点使用SockJS协议
       */
      registry.addEndpoint(GlobalConsts.ENDPOINT)
              .setAllowedOrigins("*")
              .withSockJS();
  }

}

程序结构如下:

image.png

6、 定义 POJO 类
接收客户端发过来的消息

package com.example.webscoket.vo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @program: easy
 * @description: 客户端发过来的消息
 * @author: 王震
 * @create: 2019-05-06 10:22
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClientMessage {
    private int id;
    private String name;

}

服务端返回的消息

package com.example.webscoket.vo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @program: easy
 * @description: 服务端返回消息
 * @author: 王震
 * @create: 2019-05-06 10:25
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ServerMessage {
    private String content;
}

注意,项目采用了 lombok 和 fastjson,需要在 pom 文件中加载相关依赖

    <dependency>

            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>

7、 定义 service 接口和 service 实现类

package com.example.webscoket.service;

/**
 * @Author 王震
 * @Description 消息服务接口实现
 * @Date 21:46 2019/5/6
 **/
public interface SimpMessagingService {
    /**
     * @Author 王震
     * @Description 定义消息发送模板,点对点发送
     * @Date 21:48 2019/5/6
     * @Param [user, destination, payload]
     * @return void
     **/
    void sendP2P(String user, String destination, Object payload);
}

package com.example.webscoket.service.impl;


import com.example.webscoket.service.SimpMessagingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

/**
 * @program: webscoket
 * @description: 消息服务接口实现
 * @author: 王震
 * @create: 2019-05-06 21:48
 **/
@Service
public class SimpMessagingServiceImpl implements SimpMessagingService {

    @Autowired
    private SimpMessagingTemplate template;
    /**
     * @Author 王震
     * @Description 定义消息发送模板,点对点发送
     * @Date 21:48 2019/5/6
     * @Param [user, destination, payload]
     * @return void
     **/
    @Override
    public void sendP2P(String user, String destination, Object payload) {
        template.convertAndSendToUser(user, destination, payload);
    }
}

8、 创建控制类,用于接收和响应消息

package com.example.webscoket.controller;


import com.alibaba.fastjson.JSON;
import com.example.webscoket.consts.GlobalConsts;

import com.example.webscoket.service.SimpMessagingService;
import com.example.webscoket.vo.ClientMessage;
import com.example.webscoket.vo.ServerMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;

/**
 * @program: easy
 * @description: webscoket测试controller
 * @author: 王震
 * @create: 2019-05-06 10:26
 **/
@Controller
public class ScoketController {

    @Autowired
    private SimpMessagingService simpMessagingService;

    /**
     * @Author 王震
     * @Description 接收和相应消息
     * @Date 16:42 2019/5/7
     * @Param [message]
     * @return void
     **/
    @MessageMapping(GlobalConsts.RECEIVE_MAPPING)
    public void scoket(ClientMessage message){
        simpMessagingService.sendP2P(message.getId() + "", GlobalConsts.P2PPUSHPATH, JSON.toJSON(new ServerMessage("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!")));
    }
}

9、 这样整个服务端的程序就搭建完成了,整体的代码结构如下图所示:

image.png

10、 现在编写测试程序,先下载相关的 js 库支持,如下图所示:

image.png

11、 编写测试页面,代码如下:

<!DOCTYPE html>

<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  
  <title>WebScoket测试</title>
  <script src="./test/jquery.min.js"></script>
  <script src="./test/sockjs.min.js"></script>
  <script src="./test/stomp.min.js"></script>
</head>
<body onload="disconnect()">
<div>
  <div>
      <button id="connect" onclick="connect();" disabled="">连接</button>
      <button id="disconnect" onclick="disconnect();">断开连接</button>
  </div>
  <div id="conversationDiv" style="visibility: visible;">
      <label>输入你的名字</label><input type="text" id="name">
      <button id="sendName" onclick="sendName();">发送</button>
      <p id="response"></p>
  </div>
</div>

<script type="text/javascript">
  var stompClient = null;

  function setConnected(connected) {
      document.getElementById('connect').disabled = connected;
      document.getElementById('disconnect').disabled = !connected;
      document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
      $('#response').html();
  }

  function connect() {
      // websocket的连接地址,此值等于WebSocketMessageBrokerConfigurer中registry.addEndpoint("/websocket-simple").withSockJS()配置的地址
      var socket = new SockJS('http://localhost:8080/gs-guide-websocket');
      stompClient = Stomp.over(socket);
      stompClient.connect({}, function(frame) {
          setConnected(true);
          console.log('Connected: ' + frame);
          // 客户端订阅消息的目的地址:此值BroadcastCtl中被@SendTo("/topic/getResponse")注解的里配置的值
          stompClient.subscribe('/user/' + 123 + '/msg', function(respnose){
              showResponse(JSON.parse(respnose.body).content);
          });
      });
  }


  function disconnect() {
      if (stompClient != null) {
          stompClient.disconnect();
      }
      setConnected(false);
      console.log("Disconnected");
  }

  function sendName() {
      var name = $('#name').val();
      // 客户端消息发送的目的:服务端使用BroadcastCtl中@MessageMapping("/receive")注解的方法来处理发送过来的消息
      stompClient.send("/app/receive", {}, JSON.stringify({ 'id': 123, 'name': name }));
  }

  function showResponse(message) {
      var response = $("#response");
      response.html(message + "\r\n" + response.html());
  }
</script>

</body></html>

12、 启动 java 程序,页面用浏览器打开,出现如下效果,证明搭建成功。

image.png
image.png
image.png

13、 项目下载

  • Spring

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

    941 引用 • 1458 回帖 • 153 关注
  • WebSocket

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

    48 引用 • 206 回帖 • 399 关注

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 旅游

    希望你我能在旅途中找到人生的下一站。

    85 引用 • 895 回帖 • 1 关注
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 42 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    116 引用 • 99 回帖 • 267 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 550 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    710 引用 • 1173 回帖 • 173 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 152 关注
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 422 关注
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    90 引用 • 383 回帖 • 1 关注
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    7 引用 • 26 回帖
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖 • 222 关注
  • Vue.js

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

    261 引用 • 662 回帖
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖 • 1 关注
  • 安装

    你若安好,便是晴天。

    128 引用 • 1184 回帖
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 38 关注
  • C

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

    83 引用 • 165 回帖 • 44 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    523 引用 • 4581 回帖 • 690 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖 • 2 关注
  • 自由行
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    85 引用 • 1201 回帖 • 451 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    18660 引用 • 69551 回帖
  • uTools

    uTools 是一个极简、插件化、跨平台的现代桌面软件。通过自由选配丰富的插件,打造你得心应手的工具集合。

    5 引用 • 13 回帖
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    41 引用 • 130 回帖 • 295 关注
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖 • 1 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 319 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    169 引用 • 799 回帖
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 2 关注
  • Kubernetes

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

    108 引用 • 54 回帖 • 1 关注