适配对接 Solon WebSocket 接口
此例,直接将 Solon 的 WebSocket 监器接口转换为 Socket.D 的监听器(只需要引入 Socket.D 的内核包,不需要引入传输包),方便复用 Solon 的 Http 端口。其它 WebSocket Server 接口,也可以参考此例。
引入内核包:
<dependency>
<groupId>org.noear</groupId>
<artifactId>socketd</artifactId>
<version>2.5.20</version>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-net</artifactId>
<version>最新版</version>
</dependency>
先启用 WebSocket
public class App {
public static void main(String[] args) {
Solon.start(App.class, args, app-> {
app.enableWebSocket(true);
});
}
}
1、应用示例
- Broker 应用参考
//定义 websocket 处理,并转为 socket.d 监听接口(使用 BrokerListener)
@ServerEndpoint("/demo/websocket")
public class WebSocketToSocketd extends ToSocketdWebSocketListener {
public WebSocketToSocketd() {
// clientMode=false,表示服务端模式
super(new ConfigDefault(false).fragmentHandler(new BrokerFragmentHandler()),
new BrokerListener());
}
}
- 常规应用参考
//定义 websocket 处理,并转为 socket.d 监听接口(也可以在这个类上,直接实现 Listener 接口)
@ServerEndpoint("/demo/websocket")
public class WebSocketToSocketd extends ToSocketdWebSocketListener {
//注入 socket.d 协议监听器
@Inject
Listener socketdListener;
public WebSocketToSocketd() {
// clientMode=false,表示服务端模式
super(new ConfigDefault(false));
}
@Init
public void init(){
setListener(socketdListener);
}
}
//定义 socket.d 监听实现(可以扩展 socket.d 内置的几个监听器)
@Component
public class ListenerImpl implements Listener {
...
}
2、配合 H5 演示示例:
- 前端界面(打开后,把地址和端口改成对应的)
- 配套服务端代码 - java:
@ServerEndpoint("/")
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();
});
}
}