记一次SpringBoot启动异常,jar问题的排查分析

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:jiannan.blog.csdn.net/

article/details/109641881


一、引言

小编最近接了个成功的服务端项目,在他们项目中集成了一个WebSocket,嗯,其实不难,有很多成功案例。

本文主要来记录一下,如果没有百度在自己的项目启动就抛开一些奇怪的问题,或者有一些奇奇怪怪的问题,靠自己怎么排查问题,另一种引擎去清除所有的问题都能够通过搜索来解决。

除了力,那我们就只剩下:“异常信息、来源、和自己的经验”

项目框架用的是SpringBoot,然后集成WebSocket就行,在集成的过程中,其中有一步需要配置一个Bean。

@Component
public class WsConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        ServerEndpointExporter serverEndpointExporter = new ServerEndpointExporter();
        return serverEndpointExporter;
    }

}

然后在项目启动的时候抛出了异常信息:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverEndpointExporter' defined in class path resource [org/springblade/modules/hol/config/WsConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1769)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:514)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:321)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:319)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:863)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
        at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140)
        at org.springblade.core.launch.BladeApplication.run(BladeApplication.java:50)
        at org.springblade.Application.main(Application.java:18)
        Caused by: java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
        at org.springframework.util.Assert.state(Assert.java:73)
        at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterPropertiesSet(ServerEndpointExporter.java:107)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1828)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1765)
        ... 16 common frames omitted

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

二、问题分析

在类路径资源 [org/springblade/modules/hol/config/WsConfig.class] 中定义名称为“serverEndpointExporter”的 bean 创建错误:调用 init 方法失败;嵌套异常是 java.lang.IllegalStateException: javax.websocket.server.ServerContainer 不可用

通过异常的第一行就可以得知,是在 Spring 创建“serverEndpointExporter”beanW 的时候抛出来的,是这个配置类,原因是:ServerContainer 这个对象不可使用。

抛出异常的类是:AbstractAutowireCapableBeanFactory.java:1769

分析这里就可以得知,是在spring创建serverEndpoint的时候异常了, “那么异常的原因是Exporter ,为什么ServerContainer不可用呢?” 接下来分析

通过点击转换的源码信息:AbstractAutowireCapableBeanFactory.java:1769

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
        invokeAwareMethods(beanName, bean);
        return null;
        }, getAccessControlContext());
        }
        else {
        invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
        invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
        throw new BeanCreationException(
        // 1769 这里就是1769行~~
        (mbd != null ? mbd.getResourceDescription() : null),
        beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
        }

通过查看源码,是在1796行的catch里面抛出的异常的,catch是捕捉到invokeInitMethods这个异常的方法,然后才抛出来的,这样就可以开始调试了。

我们是在创建serverendpointExporter的,加一个筛选条件beanName为serverEndpointExporter,这样再过滤创建异常的其他bean。

16c721226123bdda0840d5e4c45d8da0.png

断点卡好,下调试模式来启动项目,然后F5进到vokeInitMethods,单步往下执行。

c9caa2177da8f783125567a9d9ae62b7.png

最后执行到了 ((InitializingBean) bean).afterPropertiesSet(); 这行代码,bean方法对象是ServerEndpointExporter,调用了这个对象的afterPropertiesSet。

b0aeccd86546e1fdd643d27541b28760.png

这个ServerEndpointExporterjava类,其中就有在获取serverPropertiesSet方法之后,首先调用这个getServerContainer方法获取serverContainer对象。

很明显这里返回的肯定是null,null != null 结果肯定是false,最后就是这样调用state(false,javax.websocket.server.ServerContainer not available)

通过state源知道,最后抛出这个异常:java.lang.IllegalStateContainerException: javax.websocket.server.server not available

ec53cf7c9a859fe1946b11790b637bcc.png b48768cba36399a5d9c8a1114477aeb4.png

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

三、解决问题

通过这个文章上面的分析可以确认是因为ServerEndpoint类有一个对象为空的ExserverContainer,所以它会为空。

就需要,服务器容器这个对象是在哪里的,找源头就只有两个地方了,这就好办了。

public class ServerEndpointExporter extends WebApplicationObjectSupport
        implements InitializingBean, SmartInitializingSingleton {

    @Nullable
    private List<Class<?>> annotatedEndpointClasses;

    @Nullable
    private ServerContainer serverContainer;


    // 有一个Set方法可以为serverContainer赋值
    public void setServerContainer(@Nullable ServerContainer serverContainer) {
        this.serverContainer = serverContainer;
    }


    @Nullable
    protected ServerContainer getServerContainer() {
        return this.serverContainer;
    }


    // 有一个init方法可以为serverContainer赋值
    @Override
    protected void initServletContext(ServletContext servletContext) {
        if (this.serverContainer == null) {
            this.serverContainer =
                    (ServerContainer) servletContext.getAttribute("javax.websocket.server.ServerContainer");
        }
    }


    @Override
    public void afterPropertiesSet() {
        Assert.state(getServerContainer() != null, "javax.websocket.server.ServerContainer not available");
    }
}

通过IDEA的快捷方式,发现没有其他地方调用setServerContainer方法,那么只有init方法了,那么就断点卡在initServletContext方法了。

e5b7d28efe29b805c3de226c32c0fdc5.png

通过Bebug的能力发现,在从servletContext.getAttribute,根本就没有返回javax.websocket.ServerContainer,就是一个null的时候,结果就产生了异常给serverContainer,所以就产生了异常。

「那为什么javax.websocket.server.ServerContainer会不存在呢?」

这个类,原来是一个接口,那个ServerContainer肯定有的实现类,通过IDEA查看好人,到这个小编大概就明白了这个项目的其他jar包,引发了冲突。

099bc64472868363c4fe3f079acc784b.png

最后到是哪个罐子最后突破了,直接通过IDEA功能就能够定位到,通过maven helper工具定位到maven引用位置,然后移除掉。

33fe6fba2b9ed7a9c8b96b2614d2494c.png 1c9edf3ea7125c22a40420d2e5670dcd.png

一下maven,项目就正常启动啦~~~~~~

58b58a30928584fd63f138d7ca92f263.png

四、划重点

本文针对某个异常、或者某个具体问题的另外来进行分析,分享解决这个异常的一个过程。

最开始的小井刚毕业那会,遇到个个,运气就过好,人都踩到这个了,解决这个问题,一时也找不到很多合适的文章,然后能力,然后话就坑了咋知道办。

肯定没有其他人通过自己的问题来解决问题,而且通过自己发现问题的过程来解决自己的问题。

也有很多小伙伴问过小编,学习一些框架源码有什么用?会用不就行了吗?

怎么办呢?真的会说到底怎么办呢,那么你的话,这些奇怪的东西是怎么实现的?深层次的理解。

久而久之之,遇到主动问题,你去摸索的第一个反应自己去百度,会直接为啥子看看的异常情况,分析一下不明的源头,再去学习,进行进行。

就这样不知不觉你的技术会慢慢升华,那个时候感觉就特别明显了。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

94f0ac9beb1e0687a28f081a563a57e9.png

已在知识星球更新源码解析如下:

bfe17d13e46057ad3fec003daf7dbfb1.jpeg

9f58c4be70fc16173790a005364a59c1.jpeg

17a8e2572fd88309092c1b9fc89c6786.jpeg

8285d8c42fb6e797794839e6f1943371.jpeg

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值