
1. 為什么2024年了還要折騰Servlet模板這件事每次帶新人做Java Web入門第一節(jié)課我基本都會讓他們在IDEA里新建一個Servlet。結(jié)果十個人里有八個卡在同一個地方右鍵新建菜單里翻半天找不到Servlet選項最后手動建了個普通Java類繼承HttpServlet然后對著滿屏的紅色波浪線發(fā)呆。這個場景我見過太多次了2024年雖然Spring Boot大行其道但Servlet作為Java Web的地基依然是繞不開的一課而IDEA的Servlet模板配置恰恰是新手最容易踩坑的第一道坎。所謂IDEA創(chuàng)建Servlet模板說白了就是在IntelliJ IDEA里配置好一套代碼骨架讓你右鍵新建時能直接生成一個帶WebServlet注解、正確繼承HttpServlet、重寫doGet和doPost方法的完整類文件而不是每次從零手敲。這件事看起來小但它直接決定了你寫第一個Web程序的體驗是順暢還是抓狂。適合看這篇內(nèi)容的人很明確剛接觸Java Web的學生、從其他語言轉(zhuǎn)過來想快速跑通Servlet的開發(fā)者、以及那些用慣了Eclipse現(xiàn)在換到IDEA、發(fā)現(xiàn)怎么啥都沒有的老手。我先把結(jié)論擺出來IDEA默認不給你Servlet模板不是它忘了而是因為它把Servlet當成框架依賴而不是語言內(nèi)置。你得先讓項目認識Servlet這個類模板才有意義。所以整個配置過程其實是兩件事——讓項目能編譯Servlet以及讓IDEA能一鍵生成Servlet。很多人只做了第一件然后抱怨第二件不好用這就是問題的根源。下面我按實際操作的順序把這兩件事拆開講透順帶把2024版本里幾個容易翻車的地方提前給你標出來。2. 先搞清楚IDEA為什么看不見Servlet2.1 Servlet不在JDK里這是所有困惑的起點很多人下意識覺得Servlet是Java自帶的就像String、List一樣隨手就能用。這個誤解是后面一連串問題的源頭。Servlet規(guī)范是Java EE現(xiàn)在叫Jakarta EE的一部分它由Servlet容器提供比如Tomcat。JDK里根本沒有javax.servlet或jakarta.servlet這個包。你在IDEA里新建項目時如果只選了普通的Java項目那類路徑里自然找不到HttpServletIDEA也就不會在新建菜單里給你Servlet選項——它連這個類是什么都不知道怎么可能幫你生成模板。理解這一點之后后面的操作邏輯就順了必須先引入Servlet API依賴IDEA識別到這個類之后模板功能才會被激活。這就像你想讓IDE幫你自動補全某個第三方庫的方法前提是你得先把那個庫加到項目里。我見過有人到處找IDEA Servlet插件其實根本不需要插件缺的是依賴。2.2 2024版本里javax和jakarta的分水嶺這里有個2024年特別需要注意的坑。Servlet API的包名在歷史上有過一次大遷移老版本是javax.servlet.*從Jakarta EE 9開始改成了jakarta.servlet.*。你用的Tomcat版本決定了你該用哪個包名。Tomcat 9及以前用的是javaxTomcat 10及以后用的是jakarta。如果你依賴引的是javax但跑在Tomcat 10上啟動時就會報ClassNotFoundException或者注解不生效頁面直接404。我在實際項目里見過最典型的情況教程是幾年前寫的讓你引javax.servlet-api你照著做了IDEA里代碼一切正常沒有紅線結(jié)果一部署到Tomcat 10上就歇菜。所以配置模板之前先確認你的目標容器版本這個決定貫穿始終。下面這張表幫你快速對齊容器版本Servlet包名依賴坐標MavenTomcat 9及以下javax.servletjavax.servlet:javax.servlet-api:4.0.1Tomcat 10及以上jakarta.servletjakarta.servlet:jakarta.servlet-api:6.0.0選錯了不是代碼寫錯是根本對不上號。這一點在2024年尤其重要因為新下載的Tomcat基本都是10以上了而網(wǎng)上大量存量教程還停留在javax時代。2.3 普通Java項目與Web項目的本質(zhì)差別還有一種情況值得單獨說。IDEA新建項目時有Java和Jakarta EE老版本叫Java Enterprise之分。如果你選的是純Java項目那它壓根沒有Web模塊的概念你就算把Servlet依賴加進去能編譯也沒法直接部署運行。真正做Servlet開發(fā)建議直接建Jakarta EE項目或者用Maven建Web項目這樣IDEA會自動幫你配好Web目錄結(jié)構(gòu)web/WEB-INF和部署描述符的位置。不過話說回來現(xiàn)在很多人圖省事就用Maven建個普通項目然后手動加war打包方式和依賴也能跑。兩種路子都行區(qū)別在于前者省心、后者靈活。我個人的習慣是用Maven普通項目加手動配置因為這樣對項目結(jié)構(gòu)的理解更透徹出問題也知道去哪找。但如果你是純新手老老實實建Jakarta EE項目少走彎路。3. 讓項目先認識Servlet依賴配置的實操細節(jié)3.1 Maven方式一行依賴解決戰(zhàn)斗現(xiàn)在絕大多數(shù)項目都用Maven管理依賴這是最推薦的方式。在pom.xml的dependencies里加上對應版本的Servlet API注意scope要設成provided。為什么是provided而不是默認的compile因為Servlet API最終是由Tomcat這類容器在運行時提供的你打包成war的時候不應該把它塞進去否則可能和容器自帶的版本沖突。這個細節(jié)很多人不注意打包出來的war體積莫名變大或者部署時報類沖突根源就在這。dependency groupIdjakarta.servlet/groupId artifactIdjakarta.servlet-api/artifactId version6.0.0/version scopeprovided/scope /dependency加完之后記得點一下IDEA右上角的Maven刷新按鈕讓它重新下載并索引依賴。刷新完你可以在External Libraries里看到jakarta.servlet-api這就說明項目已經(jīng)認識Servlet了。此時你手動寫extends HttpServlet應該不再有紅線這是模板能正常工作的前提。3.2 非Maven項目手動添加庫的正確姿勢如果你用的是非Maven的普通項目那就得手動把Servlet的jar包加到項目庫里。步驟是File→Project Structure→Libraries→ 點→Java然后選中你下載好的servlet-api.jar通常在Tomcat安裝目錄的lib文件夾下就能找到比如tomcat/lib/servlet-api.jar。加進去之后還要確認這個庫被加到了當前模塊的依賴里在Modules→Dependencies里能看到它才算數(shù)。這里有個我踩過的坑直接從Tomcat的lib目錄引用jar包有時候IDEA會把它標記成模塊庫而不是項目庫導致?lián)Q個模塊就找不到。穩(wěn)妥的做法是把jar復制到項目里一個專門的lib目錄再引用這樣項目自包含換臺機器也不會丟。雖然土了點但對小項目來說最省心。3.3 驗證依賴是否真正生效配完依賴別急著建模板先做個最小驗證隨便建個Java類寫public class Test extends HttpServlet看HttpServlet能不能被正確解析、能不能Ctrl點擊跳進源碼。如果跳不進去或者標紅說明依賴沒生效這時候去配模板也是白搭。這個驗證步驟花不了三十秒但能幫你把問題定位在依賴層而不是模板層省下大量瞎折騰的時間。4. 配置Servlet模板從新建菜單找不到到一鍵生成4.1 找到模板配置的入口依賴搞定之后理論上IDEA應該能在新建菜單里給你Servlet選項了。但實際情況是有時候它還是不出現(xiàn)或者出現(xiàn)了但生成的代碼不符合你的習慣。這時候就要動模板配置了。入口在File→SettingsMac上是IntelliJ IDEA→Preferences→Editor→File and Code Templates。這個面板里Files標簽下是各種文件模板Code標簽下是代碼片段模板。Servlet模板通常在Files里名字可能叫Servlet Class或者類似的東西取決于IDEA版本和是否裝了相關(guān)插件。如果在這里找不到Servlet模板別慌可以自己建一個。點新建一個模板名字隨便起比如MyServlet擴展名填java。關(guān)鍵是模板內(nèi)容要寫對下面給你一份我用了很久、在2024版本上驗證過沒問題的模板。4.2 一份可直接抄的Servlet模板內(nèi)容#if (${PACKAGE_NAME} ${PACKAGE_NAME} ! )package ${PACKAGE_NAME};#end #parse(File Header.java) import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; WebServlet(name ${Class_Name}, urlPatterns /${Class_Name}) public class ${Class_Name} extends HttpServlet { Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(text/html;charsetUTF-8); response.getWriter().write(Hello from ${Class_Name}); } Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }這份模板里有幾個設計考量值得說清楚。${PACKAGE_NAME}和${Class_Name}是IDEA的模板變量新建時會自動替換成你輸入的包名和類名不用手改。WebServlet注解里urlPatterns默認用類名做路徑這樣新建一個叫LoginServlet的類訪問路徑自動就是/LoginServlet省去每次手動配映射。doGet里預設了UTF-8的響應編碼和一段占位輸出是因為中文亂碼是新手最高頻的問題提前設好能少踩一個坑。doPost直接委托給doGet這是最常見的簡化寫法表單提交和直接訪問行為一致調(diào)試時省事。注意如果你用的是Tomcat 9及以下把上面所有jakarta.servlet改成javax.servlet其余不變。這一步改錯模板生成的代碼全是紅線。4.3 把模板掛到新建菜單上光有模板文件還不夠得讓它出現(xiàn)在右鍵新建菜單里。在File and Code Templates面板里選中你剛建的模板注意看面板下方有沒有類似Enable live template或者關(guān)聯(lián)到具體文件類型的選項。更可靠的做法是通過Settings→Editor→File and Code Templates→Files里直接編輯已有的Servlet Class模板如果有的話這樣它天然就在新建菜單里。如果菜單里始終不出現(xiàn)還有一個辦法用Settings→Editor→Live Templates建一個代碼片段輸入縮寫比如servlet就能展開整段代碼。這種方式不依賴新建菜單在任意Java文件里敲縮寫都能用靈活度更高。我現(xiàn)在的習慣就是兩種都配新建菜單用來從零建類Live Template用來在已有文件里快速插入方法骨架。5. 模板生成之后那些模板管不到的地方5.1 web.xml還是注解2024年怎么選模板里我用的是WebServlet注解這也是現(xiàn)在的主流做法不用改web.xml類建好就能訪問。但有些老項目或者特定場景還在用web.xml配映射這時候模板生成的注解反而多余。如果你所在的項目是這種風格把模板里的WebServlet那行刪掉改成在web.xml里加servlet和servlet-mapping。兩種方式不能對同一個Servlet重復配否則啟動報錯。我的建議是新項目一律用注解清爽維護老項目就跟著老項目的規(guī)矩走別自作主張混用。5.2 部署配置里最容易漏的一步代碼寫對了、模板也生成了結(jié)果一運行404這種情況十有八九是部署配置的問題。在IDEA的Run/Debug Configurations里你得確認兩件事一是Deployment標簽下有沒有把你的artifact通常是war exploded加進去二是Application context設的是什么。如果context設成/那你訪問的路徑就是http://localhost:8080/LoginServlet如果設成/demo那就是http://localhost:8080/demo/LoginServlet。很多人路徑對不上就是因為沒注意這個context。我一般習慣設成/訪問最短調(diào)試時少打幾個字。5.3 中文亂碼模板里已經(jīng)埋了半個解決方案前面模板里response.setContentType(text/html;charsetUTF-8)解決的是響應端亂碼。但請求端的亂碼比如表單提交的中文參數(shù)變成問號還得在doGet或doPost開頭加request.setCharacterEncoding(UTF-8)。注意這行必須放在讀取任何參數(shù)之前放晚了不生效。Tomcat 8以后GET請求的編碼默認就是UTF-8了但POST請求如果不設還是可能出問題。所以嚴格來說模板里應該在doGet第一行加上這句。我上面為了模板簡潔沒加你實際用的時候建議補上尤其是要做表單處理的場景。6. 幾個我實際踩過、值得你提前避開的坑第一個坑是依賴版本和容器版本對不上前面反復強調(diào)了但還是要再說一次因為它是2024年最高頻的翻車點。判斷方法很簡單看Tomcat啟動日志里有沒有jakarta字樣或者直接看Tomcat安裝目錄下lib里那個servlet-api.jar的包結(jié)構(gòu)。對不上就改依賴別硬扛。第二個坑是模板變量寫錯導致生成的文件名不對。${Class_Name}這種變量是IDEA內(nèi)置的大小寫和拼寫必須完全一致寫成${ClassName}或者${class_name}都不會被替換生成出來就是字面量類名直接非法。我第一次配模板時就栽在這生成的文件名帶著${}編譯報一堆錯排查了半天才發(fā)現(xiàn)是變量名拼錯。第三個坑是改了模板但新建時還是老樣子。IDEA的模板有緩存改完之后有時候需要重啟IDEA或者至少File→Invalidate Caches清一下緩存才生效。如果你確認模板內(nèi)容改對了但生成結(jié)果沒變先別懷疑人生重啟一下試試八成能解決。第四個坑相對隱蔽同一個類被多個模板匹配。如果你既裝了某個插件自帶的Servlet模板又自己建了一個新建菜單里可能出現(xiàn)兩個相似選項選錯了生成出來的代碼風格和你預期不符。遇到這種情況去模板列表里把不用的那個刪掉或者禁用保持唯一入口減少誤操作。7. 關(guān)于這套配置我個人的使用體會這套模板我從幾年前一直用到現(xiàn)在中間跟著Servlet包名的遷移改過兩次整體上屬于配一次管很久的基礎設施。我的體會是模板的價值不在于省那幾十行代碼的敲擊而在于把容易出錯的約定固化下來——包名對不對、注解寫沒寫、編碼設沒設、方法簽名全不全這些細節(jié)每次手寫都可能漏模板幫你兜底。尤其是帶新人的時候讓他們用統(tǒng)一模板起步能少掉一大半為什么我的跑不起來的溝通成本。另外提一句如果你后續(xù)要往Spring MVC或者Spring Boot遷移這套Servlet模板的很多思路是相通的注解驅(qū)動、路徑映射、請求響應處理底層邏輯一脈相承。所以別覺得2024年學Servlet是浪費時間它更像是理解上層框架的一把鑰匙。模板配好之后建議你順手把doGet里的占位輸出改成讀取一個請求參數(shù)并回顯跑通一次完整的請求進來、處理、響應出去的閉環(huán)那種哦原來是這樣的感覺比看十篇教程都管用。