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. Scrum Meeting Beta - 1

    Scrum Meeting Beta - 1 NewTeam 2017/11/28 地点:主南201 任务反馈 团队成员 完成任务 计划任务 安万贺 详细讨论Beta阶段的任务和具体分工 了解缓存的相 ...

  2. Java MD5加密类

    /************************************************* md5 类实现了RSA Data Security, Inc.在提交给IETF 的RFC1321中 ...

  3. Java进行Base64的编码(Encode)与解码(Decode)

    关于base64编码Encode和Decode编码的几种方式 Base64是一种能将任意Binary资料用64种字元组合成字串的方法,而这个Binary资料和字串资料彼此之间是可以互相转换的,十分方便 ...

  4. 第82天:jQuery中prop()和attr()的区别

    在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很多.这里谈谈我的心得,我的心得很简单: ...

  5. java面试及答案

    优秀总结博客 mybatis总结 java并发包相关 一.Java基础 1.String类为什么是final的. 2.HashMap的源码,实现原理,底层结构. hashmap3.反射中,Class. ...

  6. BZOJ 1189 紧急疏散(二分+最大流)

    求出所有人撤离的最短时间.由于每扇门只能通过一次,所以不能简单用bfs来搞. 显然答案是有单调性的,考虑二分,问题变成了判断时间x所有人能不能撤离. 考虑最大流.对于每扇门,每个时间通过的人数最多为1 ...

  7. bzoj2383[CEOI2011] ballons

    题意 在一条数轴上从左向右有一些气球,每个气球一开始位于横坐标xi的位置,是半径为0的圆.现在开始从左向右给每个气球充气.被充气的气球的半径会不断变大,直到达到这个气球的半径上限Ri或者这个气球和之前 ...

  8. 【bzoj2402】陶陶的难题II 分数规划+树链剖分+线段树+STL-vector+凸包+二分

    题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ...

  9. xshell代理设置

    1.宿主机设置隧道 上面的端口随意,不与本机使用的端口重合即可,下面的端口是管理系统的端口 2.宿主机上面创建的虚机设置代理 3.怎么通过web浏览器直接登录虚机ip网址:https://blog.c ...

  10. IP组播技术

      1  概述 1.1  产生背景 传统的IP通信有两种方式:一种是在源主机与目的主机之间点对点的通信,即单播:另一种是在源主机与同一网段中所有其它主机之间点对多点的通信,即广播.如果要将信息发送给多 ...