spring-boot本身对websocket提供了很好的支持,可以直接原生支持sockjs和stomp协议。百度搜了一些中文文档,虽然也能实现websocket,但是并没有直接使用spring-boot直接支持的websocket的特性。

在实践中觉得stromp协议对于websocket开发的自由度影响比较大。这里给大家展示一种自由度比较大的方案。

主要就是三个组件,config,interceptor和handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
@EnableWebSocket
public class MessageWebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(messageWebSocketHandler(), "/sockjs/message")
.addInterceptors(new MessageWebSocketInterceptor()).withSockJS();
}
 
@Bean
public MessageWebSocketHandler messageWebSocketHandler() {
return new MessageWebSocketHandler();
}
}

config需要继承WebSocketConfigurer需要重写registerWebSocketHandlers方法,指明handler和interceptor。

interceptor顾名思义为拦截器我们可以在websocket建立之间和之后做一些事情。重载beforeHandshakeafterHandshake就OK。我在beforeHandshake这里还操作了attributes。被修改的attributes会被带到后面websocket的session之中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MessageWebSocketInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
String siteId = servletRequest.getServletRequest().getParameter("siteId");
String userId = servletRequest.getServletRequest().getParameter("userId");
if (siteId == null || userId == null) {
return false;
}
attributes.put("siteId", siteId);
attributes.put("userId", userId);
}
return true;
}
 
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
 
}
}

handler里面就可以写websocket的逻辑啦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MessageWebSocketHandler implements WebSocketHandler {
 
@Override
public void afterConnectionEstablished(WebSocketSession session) {
 
}
 
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
 
}
 
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
}
 
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
 
}
 
@Override
public boolean supportsPartialMessages() {
return false;
}
}

spring-boot单元测试可以写websocket-client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WebsocketTest {
private final Logger logger = LoggerFactory.getLogger(WebsocketTest.class);
private final WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Throwable> failure = new AtomicReference<>();
@LocalServerPort
private int port;
private SockJsClient sockJsClient;
 
@Before
public void setup() {
List<Transport> transports = new ArrayList<>();
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
transports.add(new RestTemplateXhrTransport());
this.sockJsClient = new SockJsClient(transports);
}
 
@Test
public void getGreeting() throws Exception {
 
this.sockJsClient.doHandshake(new TestWebSocketHandler(failure),
"ws://localhost:"+String.valueOf(port)+"/sockjs/message?siteId=webtrn&userId=lucy");
if (latch.await(60, TimeUnit.SECONDS)) {
if (failure.get() != null) {
throw new AssertionError("", failure.get());
}
}
else {
fail("Greeting not received");
}
 
}
 
 
 
private class TestWebSocketHandler implements WebSocketHandler {
 
private final AtomicReference<Throwable> failure;
 
TestWebSocketHandler() {
this.failure = null;
}
 
;
 
TestWebSocketHandler(AtomicReference<Throwable> failure) {
this.failure = failure;
}
 
;
 
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
logger.info("client connection established");
session.sendMessage(new TextMessage("hello websocket server!"));
}
 
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
String payload = (String) message.getPayload();
logger.info("client handle message: " + payload);
if (payload.equals("hello websocket client! webtrn lucy")) {
latch.countDown();
}
 
if (payload.equals("web socket notify")) {
latch.countDown();
}
}
 
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
logger.info("client transport error");
}
 
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
logger.info("client connection closed");
}
 
@Override
public boolean supportsPartialMessages() {
return false;
}
}
 
}

如果采用stomp协议的话可以参考spring-boot的一个ws-guide。有问题还是直接看spring文档比较好。

spring-boot支持websocket的更多相关文章

  1. spring boot 集成 websocket 实现消息主动推送

    spring boot 集成 websocket 实现消息主动 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单 ...

  2. Spring Boot 集成 WebSocket 实现服务端推送消息到客户端

    假设有这样一个场景:服务端的资源经常在更新,客户端需要尽量及时地了解到这些更新发生后展示给用户,如果是 HTTP 1.1,通常会开启 ajax 请求询问服务端是否有更新,通过定时器反复轮询服务端响应的 ...

  3. Spring Boot之WebSocket

    一.项目说明 1.项目地址:https://github.com/hqzmss/test01-springboot-websocket.git 2.IDE:IntelliJ IDEA 2018.1.1 ...

  4. spring boot: 支持jsp,支持freemarker

    spring boot: 支持jsp,支持freemarker 支持jsp: 加入依赖 <!--jsp--> <dependency> <groupId>org.a ...

  5. Spring Boot 支持多种外部配置方式

    Spring Boot 支持多种外部配置方式 http://blog.csdn.net/isea533/article/details/50281151 这些方式优先级如下: 命令行参数 来自java ...

  6. 【websocket】spring boot 集成 websocket 的四种方式

    集成 websocket 的四种方案 1. 原生注解 pom.xml <dependency> <groupId>org.springframework.boot</gr ...

  7. Spring Boot 支持 HTTPS 如此简单,So easy!

    这里讲的是 Spring Boot 内嵌式 Server 打 jar 包运行的方式,打 WAR 包部署的就不存在要 Spring Boot 支持 HTTPS 了,需要去外部对应的 Server 配置. ...

  8. Spring Boot 支持 HTTPS 如此简单,So easy!

    这里讲的是 Spring Boot 内嵌式 Server 打 jar 包运行的方式,打 WAR 包部署的就不存在要 Spring Boot 支持 HTTPS 了,需要去外部对应的 Server 配置. ...

  9. spring boot整合websocket

    转载自:https://www.cnblogs.com/GoodHelper/p/7078381.html 一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日 ...

  10. Spring Boot 系列 - WebSocket 简单使用

    在实现消息推送的项目中往往需要WebSocket,以下简单讲解在Spring boot 中使用 WebSocket. 1.pom.xml 中引入 spring-boot-starter-websock ...

随机推荐

  1. Spring – 缓存注解

    Spring缓存抽象概述 Spring框架自身并没有实现缓存解决方案,但是从3.1开始定义了org.springframework.cache.Cache和org.springframework.ca ...

  2. flink ha zk集群迁移实践

    flink为了保证线上作业的可用性,提供了ha机制,如果发现线上作业失败,则通过ha中存储的信息来实现作业的重新拉起. 我们在flink的线上环境使用了zk为flink的ha提供服务,但在初期,由于资 ...

  3. 剖析Vue原理&实现双向绑定MVVM-1

    本文能帮你做什么?1.了解vue的双向数据绑定原理以及核心代码模块2.缓解好奇心的同时了解如何实现双向绑定为了便于说明原理与实现,本文相关代码主要摘自vue源码, 并进行了简化改造,相对较简陋,并未考 ...

  4. 主流的RPC框架有哪些

    RPC是远程过程调用的简称,广泛应用在大规模分布式应用中,作用是有助于系统的垂直拆分,使系统更易拓展.Java中的RPC框架比较多,各有特色,广泛使用的有RMI.Hessian.Dubbo等.RPC还 ...

  5. (转自大富翁)LockType 属性

    指示编辑过程中对记录使用的锁定类型. 设置和返回值 设置或返回以下某个 LockTypeEnum 的值. 常量 说明 adLockReadOnly 默认值,只读.无法更改数据. adLockPessi ...

  6. Shell逐行读取文件的3种方法

    方法1:while循环中执行效率最高,最常用的方法. while read linedoecho $linedone  < filename 注释:这种方式在结束的时候需要执行文件,就好像是执行 ...

  7. Java Servlet异步处理、非阻塞I/O和文件上传

    异步处理 应用服务器中的 web容器通常对各个客户端情求分别使用一个服务器线程.在工作负载很繁重的情况下,容器常要大量线程来为所有客户端请求服务.可扩展性限制包括内存用尽,或容器线程池耗尽.为了创建可 ...

  8. C++解析(19):函数对象、关于赋值和string的疑问

    0.目录 1.函数对象 2.重载赋值操作符 3.string类 4.小结 1.函数对象 编写一个函数: 函数可以获取斐波那契数列每项的值 每调用一次返回一个值 函数可根据需要重复使用 实现功能: #i ...

  9. Mining Your Own Business UVALive - 5135(点双联通分量)

    these days I‘m tired!,but very happy... #include<cstdio> #include<cstring> #include<s ...

  10. jQuery绑定事件

    1.事件绑定的方式 事件 DOM:三种绑定方式 jQuery: #前面几种内部调用的全是on $('.c1').click() $('.c1').blur() $('.c1').aaaaa() $(' ...