1、新建maven工程

工程结构如下:

完整的pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.websocket.demo</groupId>
<artifactId>websocket-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies>
<!-- thymeleaf 模板的配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring websocket的配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

2、application.properties 的配置如下

#thymeleaf start
#spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
#开发时关闭缓存,不然没法看到实时页面
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
#thymeleaf end server.port=8082

3、启动类

package com.websocket;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; /**
* @author Administrator
* @date 2018/08/18
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}

4、WebsocketConfig 类进行了websocket的配置

package com.websocket.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; /**
* @author hzb
* @date 2018/09/30
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override
public void configureMessageBroker(MessageBrokerRegistry config) {
//启用/userTest,/topicTest,两个消息前缀
config.enableSimpleBroker("/userTest","/topicTest");
//如果不设置下面这一句,用convertAndSendToUser来发送消息,前端订阅只能用/user开头。
config.setUserDestinationPrefix("/userTest");
//客户端(html等)向服务端发送消息的前缀
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
//客户端和服务端进行连接的endpoint
stompEndpointRegistry.addEndpoint("/websocket-endpoint").setAllowedOrigins("*").withSockJS();
}
}

5、消息管理实现类

package com.websocket.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date; /**
* @author hzb
* @date 2018/09/30
*/
@Controller
@EnableScheduling
public class WebsocketMsgController { @Autowired
private SimpMessagingTemplate messagingTemplate; @GetMapping("/")
public String index() {
return "index";
} /**
* index.html将message发送给后端,后端再将消息重组后发送到/topicTest/web-to-server-to-web
* @param message
* @return
* @throws Exception
*/
@MessageMapping("/send")
@SendTo("/topicTest/web-to-server-to-web")
public String send(String message) throws Exception {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return "服务器将原消息返回: "+df.format(new Date())+" :" + message;
} /**
* 最基本的服务器端主动推送消息给前端
* @return
* @throws Exception
*/
@Scheduled(fixedRate = 1000)
public String serverTime() throws Exception {
// 发现消息
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
messagingTemplate.convertAndSend("/topicTest/servertime", df.format(new Date()));
return "servertime";
} /**
* 以下面这种方式发送消息,前端订阅消息的方式为: stompClient.subscribe('/userTest/hzb/info'
* @return
* @throws Exception
*/
@Scheduled(fixedRate = 1000)
public String serverTimeToUser() throws Exception {
// 发现消息
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//这里虽然没有指定发送前缀为/userTest,但是在WebsocketConfig.java中设置了config.setUserDestinationPrefix("/userTest"),
//否则默认为/user
messagingTemplate.convertAndSendToUser("hzb","/info", df.format(new Date()));
return "serverTimeToUser";
}
}

前端代码:index.html

<!DOCTYPE html>
<html>
<head>
<title>玩转spring boot——websocket</title>
<script src="//cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script type="text/javascript">
var stompClient = null; var app = angular.module('app', []);
app.controller('MainController', function($rootScope, $scope, $http) { $scope.data = {
connected : false,
sendMessage : '',
receivMessages : []
}; //连接
$scope.connect = function() {
var socket = new SockJS('/websocket-endpoint');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
// 订阅后端主动推消息到前端的topic
stompClient.subscribe('/topicTest/servertime', function(r) {
$scope.data.time = '当前服务器时间:' + r.body;
$scope.data.connected = true;
$scope.$apply();
});
// 阅后端主动推消息到前端的topic,只有指定的用户(hzb)收到的的消息
stompClient.subscribe('/userTest/hzb/info', function(r) {
$scope.data.hzbtime = '当前服务器时间:' + r.body;
$scope.data.connected = true;
$scope.$apply();
});
// 订阅前端发到后台,后台又将消息返回前台的topic
stompClient.subscribe('/topicTest/web-to-server-to-web', function(msg) {
$scope.data.receivMessages.push(msg.body);
$scope.data.connected = true;
$scope.$apply();
}); $scope.data.connected = true;
$scope.$apply();
});
}; $scope.disconnect = function() {
if (stompClient != null) {
stompClient.disconnect();
}
$scope.data.connected = false;
} $scope.send = function() {
stompClient.send("/app/send", {}, JSON.stringify({
'message' : $scope.data.sendMessage
}));
}
});
</script>
</head>
<body ng-app="app" ng-controller="MainController">
 
  <h2>websocket示例</h2> 
  <label>WebSocket连接状态:</label>
  <button type="button" ng-disabled="data.connected" ng-click="connect()">连接</button>
  <button type="button" ng-click="disconnect()" ng-disabled="!data.connected">断开</button>
  <br/>
  <br/>
  <div ng-show="data.connected">
<h4>以下是websocket的服务端主动推送消息到页面的例子</h4>
    <label>{{data.time}}</label> <br/> <br/>
</div>
  <div ng-show="data.connected">
<h4>以下是websocket的服务端主动推送消息到页面的例子,只有hzb这个用户收到</h4>
    <label>{{data.hzbtime}}</label> <br/> <br/>
</div>
  <div ng-show="data.connected">
<h4>以下是websocket的客户端发消息到服务端,服务端再将该消息返回到客户端(页面)的例子</h4>
<input type="text" ng-model="data.sendMessage" placeholder="请输入内容..." />
    <button ng-click="send()" type="button">发送</button>
    <br/>
    <table>
      <thead>
        <tr>
        <th>消息内容:</th>
      </tr>
       </thead>
      <tbody>
        <tr ng-repeat="messageContent in data.receivMessages">
          <td>{{messageContent}}</td>
      </tr>
       </tbody>
    </table>
</div>
</body>
</html>

运行效果

没有点“连接”之前

点了“连接”之后

输入内容:点击发送

springboot+websocket示例的更多相关文章

  1. SpringBoot + WebSocket 开发笔记

    1. 服务端的实现,我尝试了两种方式: 第一种是用“@ServerEndPoint”注解来实现,实现简单: 第二种稍显麻烦,但是可以添加拦截器在WebSocket连接建立和断开前进行一些额外操作. 不 ...

  2. Springboot+Websocket+JWT实现的即时通讯模块

    场景 目前做了一个接口:邀请用户成为某课程的管理员,于是我感觉有能在用户被邀请之后能有个立马通知他本人的机(类似微博.朋友圈被点赞后就有立马能收到通知一样),于是就闲来没事搞了一套. ​ 涉及技术栈 ...

  3. 转:php使用websocket示例详解

    原文来自于:http://www.jb51.net/article/48019.htm 这篇文章主要介绍了php使用websocket示例,需要的朋友可以参考下   下面我画了一个图演示 client ...

  4. WebSocket 示例

    websocket应运而生 在WebSocket规范提出之前,开发人员若要实现带有即时通信.实时数据.订阅推送等功能的应用实时性较强的功能,经常会使用的解决方法是 Comet. Comet是一种服务器 ...

  5. SpringBoot+WebSocket

    SpringBoot+WebSocket 只需三个步骤 导入依赖 <dependency> <groupId>org.springframework.boot</grou ...

  6. springboot+websocket+sockjs进行消息推送【基于STOMP协议】

    springboot+websocket+sockjs进行消息推送[基于STOMP协议] WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就 ...

  7. dubbo+zookeeper+springboot简单示例

    目录 dubbo+zookeeper+springboot简单示例 zookeeper安装使用 api子模块 生产者producer 消费者consumer @(目录) dubbo+zookeeper ...

  8. SpringBoot WebSocket STOMP 广播配置

    目录 1. 前言 2. STOMP协议 3. SpringBoot WebSocket集成 3.1 导入websocket包 3.2 配置WebSocket 3.3 对外暴露接口 4. 前端对接测试 ...

  9. Java Springboot webSocket简单实现,调接口推送消息到客户端socket

    Java Springboot webSocket简单实现,调接口推送消息到客户端socket 后台一般作为webSocket服务器,前台作为client.真实场景可能是后台程序在运行时(满足一定条件 ...

随机推荐

  1. 【python】入门指南1

    基础的数据结构:int, float, string 注意:python入门系列的文章的示例均使用python3来完成. #!/bin/python a = 1 b = 1.0 c = 'string ...

  2. TZOJ 2588 Bad Grass(DFS)

    描述 Bessie was munching on tender shoots of grass and, as cows do, contemplating the state of the uni ...

  3. C++ map与unordered_map

    map与unordered_map对比 map unordered_map 红黑树(非严格二叉平衡搜索树)实现 哈希表实现 有序 无序 -- 查找时间复杂度为O(1),非常快 空间消耗较大 空间消耗较 ...

  4. git 忽略 IntelliJ .idea文件

    git 忽略 IntelliJ .idea文件 2016年10月22日 11:31:27 阅读数:6196 标签: git 更多 个人分类: git   版权声明:本文为博主原创文章,未经博主允许不得 ...

  5. js中用变量作为$()内id的值、动态获取id,及获取其下面的class元素

    在开发中写了一个公共方法对模板tpl进行渲染,然而他的id是通过变量传值过来的,在网上查阅后找到解决方法,写法如下: $("#"+tplVal).html(html); 用$(&q ...

  6. C# 一段通用的写log 日志的好程序

    public void Write(string text) { FileStream fs = new FileStream(Application.StartupPath+"/log.t ...

  7. 4J - 前m大的数

    还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的M个数告诉她就 ...

  8. C++中的set

    总结一下: vector:封装了数组  list:封装了列表  map,set:封装了二叉树 set:用来存储同一类型的数据类型 非关联容器相对关联型容器插入效率高,原因是:不需要内存拷贝和内存移动, ...

  9. (轉)JSON.stringify 语法实例讲解

    作用:这个函数的作用主要是为了系列化对象的. 可能有些人对系列化这个词过敏,我的理解很简单.就是说把原来是对象的类型转换成字符串类型(或者更确切的说是json类型的).就这么简单.打个比方说,你有一个 ...

  10. PAT 1036 跟奥巴马一起编程(15)(代码)

    1036 跟奥巴马一起编程(15)(15 分) 美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统.2014年底,为庆祝"计算机科学教育周& ...