SpringBoot学习笔记(11):使用WebSocket构建交互式Web应用程序

快速开始

  本指南将引导您完成创建“hello world”应用程序的过程,该应用程序在浏览器和服务器之间来回发送消息。 WebSocket是一个非常薄,轻量级的TCP层。它使得非常适合使用“子协议”来嵌入消息。在本指南中,我们将深入研究并使用Spring的STOMP消息来创建交互式Web应用程序。

  我们将建立一个服务用来接收一个携有用户名称的消息,然后作为回应,推送一个问候语到客户订阅的队列中。

  本节内容的思维导图大致如下:

  

参考教程

https://spring.io/guides/gs/messaging-stomp-websocket/

STOMP消息

  STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,简单(流)文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。STOMP协议由于设计简单,易于开发客户端,因此在多种语言和多种平台上得到广泛地应用。

  STOMP协议的前身是TTMP协议(一个简单的基于文本的协议),专为消息中间件设计。

  STOMP是一个非常简单和容易实现的协议,其设计灵感源自于HTTP的简单性。尽管STOMP协议在服务器端的实现可能有一定的难度,但客户端的实现却很容易。例如,可以使用Telnet登录到任何的STOMP代理,并与STOMP代理进行交互。

  STOMP协议与2012年10月22日发布了最新的STOMP 1.2规范。
  要查看STOMP 1.2规范,见: https://stomp.github.io/stomp-specification-1.2.html

基于Maven构建应用

  首先,设置一个基本的构建脚本。在使用Spring构建应用程序时,您可以使用任何您喜欢的构建系统,但此处包含了使用Maven所需的代码。

  如果您不熟悉Maven,请参阅使用Maven构建Java项目。

 <!--添加WebSocket依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency> <dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-websocket</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.1.0</version>
</dependency>

创建一个资源表示类

  现在您已经设置了项目和构建系统,您可以创建STOMP消息服务。通过考虑服务交互来开始这个过程。

  该服务将接受一个包含在STOMP消息中name的消息,该消息的主体是JSON对象。如果给出的名称是“Fred”,那么消息可能如下所示:

{
"name": "Fred"
}

  要对带有name的消息建模,可以使用name属性和相应的getName()方法创建一个普通的Java对象:

public class HelloMessage {
private String name; public HelloMessage(String name){
this.name=name;
}
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

  在接收到消息并提取名称后,服务将通过创建问候语并在客户端订阅的单独队列上发布该问候语来处理它。问候语也将是一个JSON对象,可能看起来像这样:

public class GreetingMessage {
private String context; public GreetingMessage(String context) {
this.context = context;
} public String getContext() {
return context;
} public void setContext(String context) {
this.context = context;
}
}

  Spring将使用Jackson JSON库自动封送以上类型为JSON的实例。接下来,您将创建一个控制器来接收问候消息并发送问候消息。

创建一个消息处理控制器

import com.mrsaber.filebar.domain.GreetingMessage;
import com.mrsaber.filebar.domain.HelloMessage;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller; @Controller
public class GreetController { @MessageMapping("/hello")
@SendTo("/topic/greetings")
public GreetingMessage greeting(HelloMessage message) throws Exception
{
Thread.sleep(1000);
return new GreetingMessage("Hello,"+message.getName());
}
}

这个控制器看起来是简洁又简单的,但是已经做了大量的工作。让我们来分解一下这个操作。

  1.   @MessageMapping注解确保如果将消息发送到目标“/ hello”,则调用greeting()方法
  2.   消息的原数据绑定到HelloMessage对象,该对象将传递给greeting()。
  3.   在内部,该方法的实现通过使线程休眠1秒来模拟处理延迟。这是为了演示客户端发送消息后,只要需要异步处理消息,服务器就可以使用。客户可以继续进行它需要做的任何工作而无需等待响应。
  4.   在1秒延迟之后,greeting()方法创建一个Greeting对象并返回它。返回值将广播给@SendTo注解中指定的“/ topic / greetings”的所有订阅者

配置Spring以进行STOMP消息传递

  现在已经创建了服务的基本组件,您可以配置Spring以启用WebSocket和STOMP消息传递。

  创建一个名为WebSocketConfig的Java类,如下所示:

  

创建浏览器客户端

HTML部分

<!DOCTYPE html>
<html>
<head>
<title>Hello WebSocket</title>
<link href="webs/bootstrap.min.css" rel="stylesheet">
<script src="webs/jquery.min.js"></script>
<script src="webs/sockjs.min.js"></script>
<script src="webs/stomp.min.js"></script>
<script src="webs/app.js"></script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being
enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div id="main-content" class="container">
<div class="row">
<div class="col-md-6">
<form class="form-inline">
<div class="form-group">
<label for="connect">WebSocket connection:</label>
<button id="connect" class="btn btn-default" type="submit">Connect</button>
<button id="disconnect" class="btn btn-default" type="submit" disabled="disabled">Disconnect
</button>
</div>
</form>
</div>
<div class="col-md-6">
<form class="form-inline">
<div class="form-group">
<label for="name">What is your name?</label>
<input type="text" id="name" class="form-control" placeholder="Your name here...">
</div>
<button id="send" class="btn btn-default" type="submit">Send</button>
</form>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table id="conversation" class="table table-striped">
<thead>
<tr>
<th>Greetings</th>
</tr>
</thead>
<tbody id="greetings">
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

JavaScript部分

我们编写了一个app.js文件用来存放我们的业务逻辑。

var stompClient = null;

function setConnected(connected) {
$("#connect").prop("disabled", connected);
$("#disconnect").prop("disabled", !connected);
if (connected) {
$("#conversation").show();
}
else {
$("#conversation").hide();
}
$("#greetings").html("");
} function connect() {
var socket = new SockJS('localhost:8080/gs-guide-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function (greeting) {
showGreeting(JSON.parse(greeting.body).context);
});
});
} function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
} function sendName() {
stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
} function showGreeting(message) {
$("#greetings").append("<tr><td>" + message + "</td></tr>");
} $(function () {
$("form").on('submit', function (e) {
e.preventDefault();
});
$( "#connect" ).click(function() { connect(); });
$( "#disconnect" ).click(function() { disconnect(); });
$( "#send" ).click(function() { sendName(); });
});  

测试程序

SpringBoot学习笔记(11):使用WebSocket构建交互式Web应用程序的更多相关文章

  1. SpringBoot学习笔记(一)——构建springboot项目

    生成一个SpringBoot的项目 开发和学习SpringBoot需要一个生成好的SpringBoot项目. 1.可以使用一些IDE(Integrated Development Environmen ...

  2. SpringBoot学习笔记(11)-----SpringBoot中使用rabbitmq,activemq消息队列和rest服务的调用

    1. activemq 首先引入依赖 pom.xml文件 <dependency> <groupId>org.springframework.boot</groupId& ...

  3. Spring boot 官网学习笔记 - 开发第一个Spring boot web应用程序(使用mvn执行、使用jar执行)

    Creating the POM <?xml version="1.0" encoding="UTF-8"?> <project xmlns= ...

  4. SpringBoot学习笔记(14):使用SpringBootAdmin管理监控你的应用

    SpringBoot学习笔记(14):使用SpringBootAdmin管理监控你的应用 Spring Boot Admin是一个管理和监控Spring Boot应用程序的应用程序.本文参考文档: 官 ...

  5. SpringBoot学习笔记(2):引入Spring Security

    SpringBoot学习笔记(2):用Spring Security来保护你的应用 快速开始 本指南将引导您完成使用受Spring Security保护的资源创建简单Web应用程序的过程. 参考资料: ...

  6. SpringBoot学习笔记(10):使用MongoDB来访问数据

    SpringBoot学习笔记(10):使用MongoDB来访问数据 快速开始 本指南将引导您完成使用Spring Data MongoDB构建应用程序的过程,该应用程序将数据存储在MongoDB(基于 ...

  7. springboot学习笔记:9.springboot+mybatis+通用mapper+多数据源

    本文承接上一篇文章:springboot学习笔记:8. springboot+druid+mysql+mybatis+通用mapper+pagehelper+mybatis-generator+fre ...

  8. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  9. Ext.Net学习笔记11:Ext.Net GridPanel的用法

    Ext.Net学习笔记11:Ext.Net GridPanel的用法 GridPanel是用来显示数据的表格,与ASP.NET中的GridView类似. GridPanel用法 直接看代码: < ...

随机推荐

  1. winform Loading效果

    做winform项目时,有可能用到异步耗时加载数据啥的,这个时候就需要我们封装一个正在加载的效果.下面是实现思路: 步骤一:把当前form界面使用句柄的方式截图出一个图片,这个图片会在下面用到,使用句 ...

  2. Android性能优化第(二)篇---Memory Monitor检测内存泄露

    上篇说了一些性能优化的理论部分,主要是回顾一下,有了理论,小平同志又讲了,实践是检验真理的唯一标准,对于内存泄露的问题,现在通过Android Studio自带工具Memory Monitor 检测出 ...

  3. 配置和使用服务器Tomcat连接池

    1.配置Tomcat6.0根目录\conf\context.xml <?xml version='1.0' encoding='utf-8'?> <!-- Licensed to t ...

  4. linux系统故障分析与排查

    在处理Linux系统出现的各种故障时,故障的症状是最先发现的,而导致这以故障的原因才是最终排除故障的关键.熟悉Linux系统的日志管理,了解常见故障的分析与解决办法,将有助于管理员快速定位故障点.“对 ...

  5. fastjson设置生成的json属性的顺序

    目标JSON顺序: {,,} 1.url2.w3.h4.s 如果使用默认情况生成,则顺序为: w,h,s,url 在fastJson中,可以使用@JSONField来指定属性顺序(需要1.1.42以上 ...

  6. 过滤器Filter_03_多个Filter的执行顺序

    过滤器Filter_03_多个Filter的执行顺序 学习了:https://www.cnblogs.com/HigginCui/p/5772514.html 按照在web.xml中的顺序进行filt ...

  7. Codeforces Round #277.5 (Div. 2)(C题)

    C. Given Length and Sum of Digits... time limit per test 1 second memory limit per test 256 megabyte ...

  8. JAVA Eclipse开发Android如何让超出界面的部分自动显示滚动条

    在原有布局的最外围添加一层ScrollView,注意原有布局的声明也要删了 <ScrollView xmlns:android="http://schemas.android.com/ ...

  9. Nginx配置文档具体解释

    Nginx的配置文档具体解释.在这儿做个总结,以便以后使用的时间查看. 下面大部分自己整理.部分来自參考 #设置用户 #user  nobody; #启动进程数(一般和server的CPU同样) #能 ...

  10. 常见函数strlen、strcmp、strstr原型实现

    数组元素的结束符为'\0'.串的结束符为NULL 一.strlen #include <iostream> using namespace std; long h_strlen(const ...