1,首先切换到Netty这个容器并发高,轻量。首先添加配置
<!--引入启动器依赖 里面就有默认的tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除tomcat-->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入Netty-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
reload后重启,看到下面提示表示成功
2,下一步写配置接入websocket
由于netty是TCP/IP传输层的协议,而且在这个基础上不需要在引入额外的spring 配置比如
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
所以我们直接写websocket层的代码就可以。新建如下代码配置项
@Configuration
public class WebSocketConfig {
private String samplePath = "/websocket";
private long sendInterval = 500;
@Bean
public ServerHandler serverHandler() {
return new ServerHandler(sendInterval);
}
@Bean
public HandlerMapping handlerMapping(ServerHandler serverHandler) {
Map<String, WebSocketHandler> handlerByPathMap = new HashMap<>();
handlerByPathMap.put(samplePath, serverHandler);
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setUrlMap(handlerByPathMap);
handlerMapping.setOrder(-1);
return handlerMapping;
}
@Bean
public WebSocketHandlerAdapter handlerAdapter() {
return new WebSocketHandlerAdapter();
}
}
在这个配置类中,我们创建了一个 SimpleUrlHandlerMapping 对象,并使用 EchoHandler 处理器来处理 /echo 路径的 WebSocket 请求。我们还创建了一个 WebSocketHandlerAdapter 对象,它将处理器适配到 WebFlux 框架中。
创建 WebSocket 处理器
public class ServerHandler implements WebSocketHandler {
private final long interval;
public ServerHandler(long interval) {
this.interval = interval;
}
@Override
public Mono<Void> handle(WebSocketSession session) {
return new ServerLogic().doLogic(session, interval);
}
}
public class ServerLogic {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final AtomicBoolean newClient;
public ServerLogic() {
newClient = new AtomicBoolean(true);
}
public Mono<Void> doLogic(WebSocketSession session, long interval) {
return
session
.receive()
.doOnNext(message -> {
if (newClient.get()) {
logger.info("Server -> client connected id=[{}]", session.getId());
}
})
.map(message -> message.getPayloadAsText())
.doOnNext(message -> logger.info("Server -> received from client id=[{}]: [{}]", session.getId(), message))
.filter(message -> newClient.get())
.flatMap(message -> sendAtInterval(session, interval))
.doOnNext(message -> newClient.set(false))
.then();
}
private Flux<Void> sendAtInterval(WebSocketSession session, long interval) {
return
Flux
.interval(Duration.ofMillis(interval))
.map(value -> Long.toString(value))
.flatMap(message ->
session
.send(Mono.fromCallable(() -> session.textMessage(message)))
.then(
Mono
.fromRunnable(() -> logger.info("Server -> sent: [{}] to client id=[{}]", message, session.getId()))
)
);
}
}
在这个处理器中,我们实现了 WebSocketHandler 接口,并覆盖了 handle 方法。该方法接收一个 WebSocketSession 对象,通过它可以接收和发送 WebSocket 消息。我们在这个方法中创建了一个 Flux<String> 对象来接收客户端发送的消息,并使用 concatWith 将服务器发送的消息连接到该 Flux 中。最后,我们使用 WebSocketSession.send 方法将输出流中的消息发送给客户端。
下面编写一个网页端的网页客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
const socket = new WebSocket('ws://localhost:8080/websocket');
// Connection opened
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Server says:', event.data);
});
// Connection closed
socket.addEventListener('close', function (event) {
console.log('Connection closed');
});
</script>
</head>
<body>
</body>
</html>
工程目录如下
运行服务端,打开网页,可以看到相应的内容日志
服务端如下
网页端控制台打印如下
整体代码已提交到gitee,下一步我将会在这个基础上做个通用的后台,后台优先采用前后端分离模式,后台将采用vue3、vite目前UI框架待定
代码获取
私信回复springboot3获取工程代码