记录一个spring-boot-starter-websocket使用问题

 项目中的websocket突然连不上了,检查后台发现报的这个错误 No 'jakarta.websocket.server.ServerContainer' ServletContext attribute. Are you running in a Servlet container that supports JSR-356 ,经过排查终于找到原因,在此记录下

 问题复现

1. 版本

spring-boot-starter-websocket 3.2.0

dynamic-datasource-spring-boot3-starter: 4.2.0

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
            <version>4.2.0</version>
        </dependency>

2. websocket相关代码

package org.example.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {


    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry
                .addHandler(new AbstractWebSocketHandler() {
                    @Override
                    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
                        System.out.println("连接成功" + session.getId());
                    }

                    @Override
                    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
                        System.out.printf("收到%s消息%s%n", session.getId(), message.getPayload());
                        session.sendMessage(message);
                    }

                    @Override
                    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
                        System.out.println("连接断开" + session.getId());
                    }
                }, "/wsb")
                .setAllowedOrigins("*");
    }

}

3. 使用postman工具进行测试,发现连不上,报的500错误

 报错信息如下

2024-03-20T09:47:41.877+08:00 ERROR 10176 --- [io-10090-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.web.socket.server.HandshakeFailureException: Uncaught failure for request http://localhost:10090/wsb - No 'jakarta.websocket.server.ServerContainer' ServletContext attribute. Are you running in a Servlet container that supports JSR-356?] with root cause

java.lang.IllegalArgumentException: No 'jakarta.websocket.server.ServerContainer' ServletContext attribute. Are you running in a Servlet container that supports JSR-356?

寻找原因

从报错信息来看好像是容器不支持 jsr-356(jsr-356应该是websocket的意思),从启动信息来看用的容器是tomcat 10.1.6,这个是肯定支持websocket的,所以不是这个问题

 查看其它依赖有没有引入其它容器,发现dynamic-datasource-spring-boot3-starter竟然引了undertow的依赖,可能是一个项目同时引了tomcat和undertow的starter导致了这个问题

排除undertow的依赖重启服务,再次测试,websocket可以正常连接和使用

解决方法

1. 排除dynamic-datasource-spring-boot3-starter中的undertow依赖

            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-undertow</artifactId>
                </exclusion>
            </exclusions>

2. 查了一下其它版本的依赖,发现好像只有4.2.0版本有undertow的依赖,所以使用dynamic-datasource-spring-boot3-starter其它依赖版本也可以,如4.3.0

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值