用 Spring boot 实现 web socket 应用

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

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 回帖 • 148 关注
  • WebSocket

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

    48 引用 • 206 回帖 • 389 关注

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 696 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 5 关注
  • Kubernetes

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

    108 引用 • 54 回帖 • 1 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    215 引用 • 462 回帖
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖
  • IDEA

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

    180 引用 • 400 回帖 • 1 关注
  • CodeMirror
    1 引用 • 2 回帖 • 120 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    11 引用 • 5 回帖 • 568 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • OnlyOffice
    4 引用 • 16 关注
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    60 引用 • 287 回帖
  • Tomcat

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

    162 引用 • 529 回帖 • 1 关注
  • 安装

    你若安好,便是晴天。

    130 引用 • 1184 回帖
  • 旅游

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

    85 引用 • 895 回帖
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 22 关注
  • AngularJS

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

    12 引用 • 50 回帖 • 431 关注
  • 游戏

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

    169 引用 • 800 回帖 • 1 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 607 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    51 引用 • 190 回帖 • 1 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 347 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    140 引用 • 441 回帖
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 4 关注
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖 • 1 关注
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖 • 1 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    311 引用 • 546 回帖 • 35 关注
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 633 关注