Spring Chapter4 WebSocket 胡乱翻译 (一)
4. WebSocket
包含了Servlet stack,原生WebSocket交互,通过SockJS模拟,并且通过STOMP在WebSocket之上订阅、发布消息。
4.1 简介
不扯了,看到这个地方的都已经知道WebSocket是干啥的,用在啥地方。
4.2 WebSocket API
Spring框架提供了WebSocket的API,可以用来写处理WebSocket消息的client和server的程序。
4.2.1 WebSocketHandler
创建一个WebSocket服务器很简单,实现WebSockHandler接口就完事了。或者更具体点,继承TextWebSocketHandler或者BinaryWebSocketHandler:
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;
public class MyHandler extends TextWebSocketHandler {
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
// ...
}
}
通过下面的java代码将上面的Handler配置到具体的URL上:
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
在SpringMVC应用里,上面的配置可以可以包含在DispatcherServlet的配置中。然而,Spring WebSocket可以独立于SpringMVC。通过WebSocketHttpRequestHandler可以把WebSocketHandler集成到其他的HTTP服务环境中。
4.2.2 WebSocket握手
自定义初始HTTP WebSocket握手请求的最简单的方法是通过HandShakeInterceptor,它提供了“before”和“after”握手方法。这些拦截器可以用来阻止握手或者让WebSocketSession得到一下属性。例如,有一个内置的拦截器,可以用来向WebSocket的session传递HTTP的session的属性。
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyHandler(), "/myHandler")
.addInterceptors(new HttpSessionHandshakeInterceptor());
}
}
更高级的选项是继承DefaultHandshakeHandler,它执行WebSocket握手步骤,包括验证客户端来源,协商子协议等。如果应用程序需要配置自定义RequestUpgradeStrategy以适应WebSocket服务器引擎和尚不支持的版本,则应用程序可能还需要使用此选项(有关此主题的更多信息,请参阅部署)。
4.2.3 部署
Spring WebSocket API易于集成到Spring MVC应用程序中,其中DispatcherServlet同时提供HTTP WebSocket握手以及其他HTTP请求。 通过调用WebSocketHttpRequestHandler,也可以轻松地集成到其他HTTP处理场景中。 这很方便易懂。 但是,JSR-356 runtimes有些特殊注意事项。
Java WebSocket API(JSR-356)提供了两种部署机制。
- 第一个涉及启动时的Servlet容器classpath扫描(Servlet 3功能);
- 另一个是在Servlet容器初始化时使用的注册API。
这些机制都不能使用单个“前端控制器”进行所有HTTP处理 - 包括WebSocket握手和所有其他HTTP请求 - 例如Spring MVC的DispatcherServlet。
这是JSR-356的一个重要限制,Spring的WebSocket支持即使在JSR-356运行时运行时也能解决特定于服务器的RequestUpgradeStrategy问题。 Tomcat,Jetty,GlassFish,WebLogic,WebSphere和Undertow(以及WildFly)目前存在这样的策略。 (这段没看太明白,WEBSOCKET_SPEC-211可以解决这个问题)
第二个考虑因素是具有JSR-356支持的Servlet容器应该执行ServletContainerInitializer(SCI)扫描,这可能会减慢应用程序启动速度,在某些情况下会显着降低。 如果在升级到支持JSR-356的Servlet容器版本后观察到重大影响,则应该可以通过在web.xml中使用<absolute-ordering />元素来选择性地启用或禁用Web片段(和SCI扫描).
4.2.4 Server配置
每个底层WebSocket引擎都公开控制运行时特性的配置属性,例如消息缓冲区大小,空闲超时等。
对于Tomcat,WildFly和GlassFish,将ServletServerContainerFactoryBean添加到WebSocket Java配置中:
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer { @Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
}
对于client端,使用ContainerProvider.getWebSocketContainer()来配置。(XML中用WebSocketContainerFactoryBean)
4.2.5 Allowed origins
hmmm,暂时没啥用,用的时候网上一搜一大堆~~
4.3 SockJS方案
模拟器,在原生WebSocket API不能用的情况下,通过SockJS继续实现功能。
4.3.1 概要
就那回事吧,不写了。
4.3.2 启用SockJS
很简单,通过java代码即可:
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler").withSockJS();
}
在浏览器里,程序可以使用sockjs-client来搞事情。
4.3.3 IE8,9
跳过这节,现在用Ubuntu呢:)
4.3.4 心跳
SockJS需要服务器发送心跳信号来防止连接挂掉。Spring SockJS配置有个属性叫做heartbeatTime,可以用来自定义心跳频率。默认在没有通讯25秒之后跳。
Spring SockJS也支持配置一个TaskScheduler来调度心跳任务。
4.3.5 Client disconnects
客户端断开了,但是服务器不知道。得注意。
4.3.6 SockJS和CORS
这个暂时也用不上。
4.3.7 SockJS Client
可以提供测试。一个Java的SockJS的Client。
4.4 STOMP
WebSocket只定义了2种消息:Test和Binary,但是没定义它们的内容。这是和STOMP出现了,定义了消息的种类,格式和内容。
4.4.1 概述
客户端可以使用SEND或SUBSCRIBE命令发送或订阅消息以及“目标”标头,该标头描述消息的内容以及应由谁接收消息。这启用了一个简单的发布 - 订阅机制,可用于通过代理将消息发送到其他连接的客户端,或者向服务器发送消息以请求执行某些工作。
使用Spring的STOMP支持时,Spring WebSocket应用程序充当客户端的STOMP代理。消息被路由到@Controller消息处理方法或者路由到一个简单的内存代理,该代理跟踪订阅并向订阅用户广播消息。您还可以将Spring配置为使用专用的STOMP代理(例如RabbitMQ,ActiveMQ等)来实现消息的实际广播。在这种情况下,Spring维护与代理的TCP连接,向其中继消息,并将消息从其传递到连接的WebSocket客户端。因此,Spring Web应用程序可以依赖于基于HTTP的统一安全性,通用验证以及熟悉的编程模型消息处理工作。
这是订阅接收股票报价的客户的示例,服务器可以周期性地发出该报价。通过计划任务通过SimpMessagingTemplate将消息发送到代理:
SUBSCRIBE
id:sub-1
destination:/topic/price.stock.*
^@
以下是客户端发送交易请求的示例,服务器可以通过@MessageMapping方法处理该交易请求,稍后在执行后,向客户端广播交易确认消息和详细信息:
SEND
destination:/queue/trade
content-type:application/json
content-length:44 {"action":"BUY","ticker":"MMM","shares",44}^@
在STOMP规范中故意将目的地的含义保持不透明。 它可以是任何字符串,完全取决于STOMP服务器,以定义它们支持的目标语义和语法。 然而,很常见的是,目标是类似路径的字符串,其中“/ topic / ..”表示发布 - 订阅(一对多),“/ queue /”表示点对点(一对一) -one)消息交换。
使用MESSAGE来广播消息到所有客户端:
MESSAGE
message-id:nxahklf6-1
subscription:sub-1
destination:/topic/price.stock.MMM {"ticker":"MMM","price":129.45}^@
知道服务器无法发送未经请求的消息非常重要。 来自服务器的所有消息必须是特定的客户端订阅的响应,并且服务器消息的“subscription-id”头必须与客户端订阅的“id”头匹配。 以上概述旨在提供对STOMP协议的最基本的了解。 建议完整地查看协议规范。
4.4.2 好处
不用多说了,不用再造轮子了,直接开干。
4.4.3 启用STMOP
spring-messaging和spring-websocket模块里有STOMP的支持。你可以使用STOMP的endpoint:
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/portfolio").withSockJS(); //①
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app"); //②
config.enableSimpleBroker("/topic", "/queue"); //③
}
}
客户端,可以使用JSteunou/webstomp-client:
var socket = new SockJS("/spring-websocket-portfolio/portfolio");
var stompClient = webstomp.over(socket);
stompClient.connect({}, function(frame) {
}
或者通过WebSocket(没有SockJS)
var socket = new WebSocket("/spring-websocket-portfolio/portfolio");
var stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) {
}
Spring Chapter4 WebSocket 胡乱翻译 (一)的更多相关文章
- Spring Chapter4 WebSocket 胡乱翻译 (二)
书接上文,Spring Chapter4 WebSocket 胡乱翻译 (一) 4.4.4. 消息流 一旦暴露了STOMP端点,Spring应用程序就成为连接客户端的STOMP代理. 本节介绍服务器端 ...
- Spring Chapter4 WebSocket 胡乱翻译 (一) 一个例子
因为没有基础,不知道从哪里入手. 文档里的例子,https://github.com/rstoyanchev/spring-websocket-portfolio,这个除了WebSocket,还整了S ...
- 玩转spring boot——websocket
前言 QQ这类即时通讯工具多数是以桌面应用的方式存在.在没有websocket出现之前,如果开发一个网页版的即时通讯应用,则需要定时刷新页面或定时调用ajax请求,这无疑会加大服务器的负载和增加了客户 ...
- spring boot websocket stomp 实现广播通信和一对一通信聊天
一.前言 玩.net的时候,在asp.net下有一个叫 SignalR 的框架,可以在ASP .NET的Web项目中实现实时通信.刚接触java寻找相关替代品,发现 java 体系中有一套基于stom ...
- Spring Boot WebSocket从入门到放弃
在构建Spring boot项目时已经提供webSocket依赖的勾选.webSocket是TCP之上的一个非常薄的轻量级层 ,webSocket主要的应用场景离不开即时通讯与消息推送,但只要应用程序 ...
- spring集成webSocket实现服务端向前端推送消息
原文:https://blog.csdn.net/ya_nuo/article/details/79612158 spring集成webSocket实现服务端向前端推送消息 1.前端连接webso ...
- Spring之WebSocket网页聊天以及服务器推送
Spring之WebSocket网页聊天以及服务器推送 转自:http://www.xdemo.org/spring-websocket-comet/ /Springframework /Spring ...
- spring对websocket的集成和使用
WebSocket是HTML5提出的一个用于通信的协议规范,该协议通过一个握手机制,在客户端和服务端之间建立一个类似于TCP的连接,从而方便客户端和服务端之间的通信. WebSocket协议本质上是一 ...
- Spring整合WebSocket
WebSocket,干什么用的?我们有了HTTP,为什么还要用WebSocket?很多同学都会有这样的疑问.我们先来看一个场景,大家的手机里都有微信,在微信中,只要有新的消息,这个联系人的前面就会有一 ...
随机推荐
- 洛谷P3355 骑士共存问题(最小割)
传送门 de了两个小时的bug愣是没发现错在哪里……没办法只好重打了一遍竟然1A……我有点想从这里跳下去了…… 和方格取数问题差不多,把格子按行数和列数之和的奇偶性分为黑的和白的,可以发现某种颜色一定 ...
- spark执行例子eclipse maven打包jar
首先在eclipse Java EE中新建一个Maven project具体选项如下 点击Finish创建成功,接下来把默认的jdk1.5改成jdk1.8 然后编辑pom.xml加入spark-cor ...
- 2018数学建模A题优秀论文:高温作业专用服装设计
高温作业专用服装设计 摘 要 本文针对多层材料的高温作业服装的传热问题进行研究,综合考虑多种传热方式建立传热模型,并以此模型为基础解决了服装设计中各层材料最佳厚度的问题. 对于问题一,要求在热物性系数 ...
- CentOS71611部署Django
web.conf <VirtualHost *:> WSGIScriptAlias / /var/www/datacn/datacn/wsgi.py Alias /static/ /var ...
- Puppet全面详解
1. 概述 puppet是一个开源的软件自动化配置和部署工具,它使用简单且功能强大,正得到了越来越多地关注,现在很多大型IT公司均在使用puppet对集群中的软件进行管理和部署,如google利用p ...
- [集合]线程安全的HashMap
一.一般模式下线程安全的HashMap 默认情况常用的HashMap都是线程不安全的,在多线程的环境下使用,常常会造成不可预知的,莫名其妙的错误.那么,我们如何实现一个线程安全的HashMap呢?其中 ...
- java集合之Set接口
Set集合通常不能记住元素添加的顺序,其他的操作和它的父接口基本相同.只是行为上有细微的差别,Set集合不能包含相同的元素.如果尝试添加相同的元素,调用add()方法将返回false,且新元素不能被加 ...
- SQL 单引号转义
declare @userNum varchar(50),@waterNum varchar(50),@tableName varchar(20),@sql varchar(max) select @ ...
- 利用EFCore 封装Repository(可扩展不同数据的sql操作)
本篇是对EFCore 进行下封装并实现基本的增删改查的同步异步方法及针对不同数据库的批量插入.sql语句直接操作数据库: 一. 先定义基础仓储接口IRepository public interfac ...
- C++_类和动态内存分配5-使用指向对象的指针
再探new和delete new为创建的每一个对象的名称字符串分配存储空间,这是在构造函数中进行的: 析构函数使用delete来释放这些内存. 字符串是一个字符数组,所以析构函数使用的是带中括号的de ...