适配对接 SpringBoot WebSocket 接口
此例,直接将 SpringBoot 的 WebSocket 监器接口转换为 Socket.D 的监听器(引入一个转换包),方便复用 SpringBoot 的 Http 端口。其它 WebSocket Server 接口,也可以参考此例。
引入专门的适配 SDK(兼容 jetty, undetow):
<dependency>
<groupId>org.noear</groupId>
<artifactId>socketd-transport-spring-websocket</artifactId>
<version>2.5.12</version>
</dependency>
适配 SDK 不面要启动 server,只需要注册 websocket 即可。通过协议转换,实现 socket.d 协议。
1、应用示例
- 配置 WebSocket
//配置 websocket
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Resource
private WebSocketToSocketd webSocketToSocketd;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketToSocketd,"/demo/websocket")
.setAllowedOrigins("*");
}
}
- 实现 WebSocket 监听与转换
定义 websocket 处理,并转为 socket.d 监听接口(也可以在这个类上,直接实现 Listener 接口)
//示例1(设置监听器,也可以注入)
@Component
public class WebSocketToSocketd extends ToSocketdWebSocketListener {
public WebSocketToSocketd() {
super(new ConfigDefault(false).useSubprotocols(true)); //如果客户端不支持子协议验证,可以设为 false
//设置 socket.d 监听
setListener(new EventListener().doOnOpen(s -> {
}).doOn("/demo", (s, m) -> {
}));
}
}
//示例2(直接实现 socket.d 监听)
@Component
public class WebSocketToSocketd extends ToSocketdWebSocketListener implements Listener{
public WebSocketToSocketd() {
super(new ConfigDefault(false));
}
@Override
public void onOpen(Session session) throws IOException {
}
@Override
public void onMessage(Session session, Message message) throws IOException {
if("/demo".equals(message.event())){
}
}
@Override
public void onClose(Session session) {
}
@Override
public void onError(Session session, Throwable error) {
}
}
2、配合 H5 演示示例:
- 前端界面(打开后,把地址和端口改成对应的)
- 配套服务端代码 - java:
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
private WebSocketToSocketd webSocketToSocketd = new WebSocketToSocketd();
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketToSocketd, "/")
.setAllowedOrigins("*");
}
}
public class WebSocketToSocketd extends ToSocketdWebSocketListener {
public WebSocketToSocketd() {
super(new ConfigDefault(false));
setListener(buildListener());
}
/**
* 构建监听器
*/
private Listener buildListener() {
return new EventListener()
.doOnOpen(s -> {
System.out.println("onOpen: " + s.sessionId());
}).doOnMessage((s, m) -> {
System.out.println("onMessage: " + m);
}).doOn("/demo", (s, m) -> {
if (m.isRequest()) {
s.reply(m, new StringEntity("me to!"));
}
if (m.isSubscribe()) {
int size = m.metaAsInt(EntityMetas.META_RANGE_SIZE);
for (int i = 1; i <= size; i++) {
s.reply(m, new StringEntity("me to-" + i));
}
s.replyEnd(m, new StringEntity("welcome to my home!"));
}
}).doOn("/upload", (s, m) -> {
if (m.isRequest()) {
String fileName = m.meta(EntityMetas.META_DATA_DISPOSITION_FILENAME);
if (StrUtils.isEmpty(fileName)) {
s.reply(m, new StringEntity("no file! size: " + m.dataSize()));
} else {
s.reply(m, new StringEntity("file received: " + fileName + ", size: " + m.dataSize()));
}
}
}).doOn("/download", (s, m) -> {
if (m.isRequest()) {
FileEntity fileEntity = new FileEntity(new File("/Users/noear/Movies/snack3-rce-poc.mov"));
s.reply(m, fileEntity);
}
}).doOn("/push", (s, m) -> {
if (s.attrHas("push")) {
return;
}
s.attrPut("push", "1");
while (true) {
if (s.attrHas("push") == false) {
break;
}
s.send("/push", new StringEntity("push test"));
RunUtils.runAndTry(() -> Thread.sleep(200));
}
}).doOn("/unpush", (s, m) -> {
s.attrMap().remove("push");
})
.doOnClose(s -> {
System.out.println("onClose: " + s.sessionId());
}).doOnError((s, err) -> {
System.out.println("onError: " + s.sessionId());
err.printStackTrace();
});
}
}