出現的問題:
今天自己新建了一個maven webapp項目,准備自己看看springboot的東西,搭好的項目是這樣的
一切都很正常啊,用run App的方式直接啟動
成功啦,本應該到此結束,喝茶吃飯去,腦子一抽,不對,平時我們線上都是外部tomcat跑程序,要不我也用tomcat跑跑。tomcat很快就跑起來了,再一想,好像平時web項目都是用jetty調試的嘛,干嘛用tomcat跑呢,用jetty跑跑唄。
run jetty,go。。。咦
這是什么鬼,仔細看看,怎么從jetty跑到tomcat里面去了?腦子有點亂,這倆根本不是一家啊
問題解決:
不管怎么樣,ServletContext的getVirtualServerName方法沒找到,先google一下吧,stackoverflow上都是說項目里引入servlet-api-2.5,而這個方法是3.1以后才有的,mvn dependency:tree看一下,沒有引入啊,
想不起來從哪看來個solution,改一下web app版本,想想對啊,javax是jdk里面的吧,web app版本可能會影響使用的servlet
狠點,直接改成3.0吧,想必是這個,改了還報錯,最后各種解決報錯,還是不行,這條路走了很久,發現錯了。
旁邊應姓大牛看不下去了,曰:這個servlet-api不是jdk里面的,應該是jetty運行需要的吧
有道理啊,下個jetty看看,曰:@%&¥@¥
還真是jetty8用的servlet-api 3.0,下個高版本的jetty run看看,jetty9用的servlet3.1
go,我的神啊,
吃飯吃飯。。。
思考:
吃完飯回了,聽歌睡睡覺吧,腦子閃過個tomcat,剛剛不是報錯是tomcat么,為什么jetty run會跑到tomcat里面去呢,再看看報錯,
先看看WsServerContainer吧,恩,好像在設置線程組的時候用到這個方法了,
還是從源頭找吧,從jetty-plus里面的ContainerInitializer的callStartup方法進入tomcat的,就是這里
看看_target是什么吧,
這是servlet容器吧,有點明朗了,springboot內嵌的tomcat里面有這個ServletContainerInitializer,先被加載了,jetty再把自己初始化出來的servletContext傳給它,jetty的servlet-api沒有getVitualServerName方法,所以tomcat那邊報錯了,由此推理,應該tomcat的ServletContext接口應該有這個方法,看看吧,
真有這個方法,而且tomcat就是牛逼,直接把javax.servlet抄過來了,這樣就擺脫了對Servlet-api依賴了,以前寫項目都是這么干的么,還是別的原因,大牛教教我吧
既然用jetty跑,就把tomcat去掉吧
排除內嵌的tomcat后,直接用jetty是可以的。
總結:仔細看報錯代碼,從報錯源頭查起,all in one,沒事別瞎幾把折騰。。。