昨天開始學習Java Web中的Servlet,學到用IntelliJ IDEA創建Java Web項目時,跟着課程上老師的步驟一步步做,卻發現運行時Servlet找不到。坑爹的是,練習建項目時,一模一樣的操作過程,走了幾遍,有的沒問題,有的有問題。
創建項目的過程:
- 新建Maven項目,不使用任何Archetype
- 創建目錄:
<項目根目錄>/src/main/webapp/
- 在Project Structure的Modules中添加Web
- 將Deployment Descriptors和Web Resource Directories的項都做到
<項目根目錄>/src/main/webapp/
- 點擊自動提示的“Create Artifact”自動創建一個Artifact(類型:Web Application: Exploded)
- 在Run/Debug Configuration中添加Tomcat Server,其中添加上面的Artifact,能正常啓動
- 在
<項目根目錄>/src/main/webapp/
添加HTML文件、JSP文件等,都能正常訪問 - 在
<項目根目錄>/src/main/
中編寫Servlet,不能訪問,報ClassNotFoundException
觀察Java Web的輸出目錄<項目根目錄>/out/artifacts/xxx_Web_exploded/
可以發現,WEB-INF/
目錄下根本沒有classes/
目錄,那麼當然找不到Servlet。此外,對比沒出問題的項目,可以發現連Maven的輸出目錄<項目根目錄>/target/
都沒有。手動mvn compile
,此時target/
目錄纔會生成,但即使在此基礎上再做rebuild Artifact,其中的.class文件也不會複製到WEB-INF/
中。
所以問題的直接原因很明瞭,就是IDE根本就沒有做Servlet的編譯和字節碼文件複製。
在IDE中的操作過程都是一樣的,所以盯着界面找了半天也沒找到什麼不同。最終,通過使用VSCode直接一一diff正常項目和問題項目文件的辦法,找到了出問題的地方——IDEA項目的.iml文件。
在項目的.iml文件中,有這麼一段:
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
將這一段刪除,再重啓Tomcat,發現target/
目錄和WEB-INF/classes/
目錄馬上就都有了,此時程序運行就一切正常了。
我暫時沒去專門查資料搞清這一段到底是什麼含義,具體是什麼機制導致了上面的現象,有知道的朋友可以留言說一下。