<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          記一次SpringBoot啟動(dòng)異常,jar沖突問題的排查分析

          共 11598字,需瀏覽 24分鐘

           ·

          2022-07-24 21:34

          你知道的越多,不知道的就越多,業(yè)余的像一棵小草!

          你來,我們一起精進(jìn)!你不來,我和你的競(jìng)爭(zhēng)對(duì)手一起精進(jìn)!

          編輯:業(yè)余草

          jiannan.blog.csdn.net

          推薦:https://www.xttblog.com/?p=5351

          一、引言

          小編最近接了個(gè)相當(dāng)于外包的項(xiàng)目,在他們項(xiàng)目中集成一個(gè) WebSocket 的服務(wù)端,嗯功能其實(shí)不難,但是前方有坑。

          本文主要來記錄一下,如果沒有了百度,在項(xiàng)目啟動(dòng)就拋異常、或者一些奇奇怪怪的問題,靠自己怎么去排查問題,同樣有時(shí)候并不是所有的問題都能夠通過搜索引擎來解決。

          除了外力,那我們就只剩下:「異常信息、源碼、和本身經(jīng)驗(yàn)」。

          項(xiàng)目框架用的是SpringBoot,然后集成WebSocket就行,在集成的過程中,其中有一步需要配置一個(gè)Bean。

          @Component
          public class WsConfig {

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

          }

          然后在項(xiàng)目啟動(dòng)的時(shí)候拋出了異常信息:

          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

          二、問題分析

          ?

          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

          ?

          通過異常的第一行就能夠得知,是在Spring創(chuàng)建“serverEndpointExporter”bean的時(shí)候拋出來的,是這個(gè)WsConfig類,原因是:ServerContainer這個(gè)對(duì)象不可使用。

          拋出異常的類是:AbstractAutowireCapableBeanFactory.java:1769

          分析到這里就能夠得知,是在spring創(chuàng)建serverEndpointExporter的時(shí)候異常了,「那么異常的原因是什么呢?,為什么ServerContainer不可用呢?」  接著分析

          通過控制臺(tái)點(diǎn)擊到對(duì)應(yīng)的源碼信息如下: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這個(gè)方法異常,然后才拋出來的,這樣就可以開始進(jìn)行Debug了。

          既然是在創(chuàng)建serverEndpointExporter這個(gè)bean異常的,加一個(gè)篩選條件,beanName等于serverEndpointExporter,這樣就能過濾創(chuàng)建的其他bean。

          斷點(diǎn)卡好了,接下來就Debug模式來啟動(dòng)項(xiàng)目,然后F5進(jìn)到invokeInitMethods方法,單步往下執(zhí)行。

          最后執(zhí)行到了 ((InitializingBean) bean).afterPropertiesSet(); 這行代碼,bean對(duì)象是ServerEndpointExporter,調(diào)用了這個(gè)對(duì)象的afterPropertiesSet方法。

          來到ServerEndpointExporter這個(gè)java類,其中就會(huì)有afterPropertiesSet方法,首先調(diào)用getServerContainer方法獲取serverContainer對(duì)象。

          很明顯這里返回的肯定是null,null != null 結(jié)果肯定是false,最后就是這樣調(diào)用state(false,javax.websocket.server.ServerContainer not available)

          通過state源碼得知,最后就會(huì)拋出這個(gè)異常:java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available

          三、解決問題

          通過文章上述分析,可以確認(rèn)是因?yàn)镾erverEndpointExporter這個(gè)類中有一個(gè)對(duì)象叫做serverContainer,它為null了,所以才會(huì)異常。

          接下來我們就需要去找,serverContainer這個(gè)對(duì)象是在哪里賦值的,找源碼就只有兩處賦值了,這就好辦了。

          public class ServerEndpointExporter extends WebApplicationObjectSupport
            implements InitializingBeanSmartInitializingSingleton 
          {

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

              @Nullable
              private ServerContainer serverContainer;


              // 有一個(gè)Set方法可以為serverContainer賦值
              public void setServerContainer(@Nullable ServerContainer serverContainer) {
                      this.serverContainer = serverContainer;
              }


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


          // 有一個(gè)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的快捷方式,發(fā)現(xiàn)沒有其他地方調(diào)用了setServerContainer方法,那么就只有init方法了,那么就把斷點(diǎn)卡在initServletContext方法這。

          通過Bebug就能夠發(fā)現(xiàn),在從servletContext.getAttribute的時(shí)候,根本就沒有javax.websocket.server.ServerContainer,所以getAttribute返回就是一個(gè)null,最后賦值給了serverContainer,最后就導(dǎo)致異常了。

          「那為什么javax.websocket.server.ServerContainer會(huì)不存在呢?」

          來到這個(gè)ServerContainer對(duì)應(yīng)的java類,原來是一個(gè)interface,那必然就會(huì)有對(duì)應(yīng)的實(shí)現(xiàn)類,通過IDEA查看好家伙,到這小編大概就明白了,這個(gè)項(xiàng)目引用了其他jar包,導(dǎo)致了沖突。

          最后定位到是哪個(gè)jar沖突了,直接通過IDEA定位功能就能夠定位到,最后通過maven helper工具定位到maven引用位置,然后移除掉。

          最后刷新一下maven,項(xiàng)目就能夠正常啟動(dòng)啦~~~~~

          四、劃重點(diǎn)

          本文并不是針對(duì)某一個(gè)異常、或者某一個(gè)具體的問題來進(jìn)行分析,而是分享一下解決這個(gè)異常的一個(gè)過程。

          最初的小編剛畢業(yè)那會(huì),遇到個(gè)異常就百度,運(yùn)氣好的話,很多人都踩過這個(gè)坑,能夠解決,萬一恰好沒有找到合適的文章,然后、然后就陷入了沉思,也不知道咋辦。

          而且通過別人來解決的問題,肯定沒有自己解決問題的印象深刻,而且通過自己去找問題也是個(gè)有趣的過程。

          也有很多小伙伴問過小編,學(xué)習(xí)一些框架源碼有什么用?會(huì)用不就行了嗎?

          怎么說呢?當(dāng)然確實(shí)會(huì)用就行了,話又說話來,難道你就不好奇它們這些技術(shù)到底是怎么實(shí)現(xiàn)的嗎?看源碼不僅僅能夠?qū)W習(xí)到其他大神編寫代碼的風(fēng)格,而且對(duì)于使用也有會(huì)更加深一層次的理解。

          久而久之,遇到問題,你的第一反應(yīng)并不是直接去百度,而是會(huì)自己主動(dòng)去摸索,到底是為啥子異常的,碰到一些看不懂的源碼,再去百度學(xué)習(xí)一下,進(jìn)行分析。

          就這樣不知不覺你的技術(shù)就會(huì)慢慢得到升華,那個(gè)時(shí)候感覺就特別明顯了。

          瀏覽 135
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天插日日干 | 69av成人 | 特一级黄色视频 | 蜜桃视频久久一区免费观看入口 | 国产一区二区在线播放 |