IDEA创建Servlet完整流程:从Maven工程到Tomcat部署

发布时间:2026/10/20 13:49:09

IDEA创建Servlet完整流程:从Maven工程到Tomcat部署 作为常年和 Servlet 打交道的老手我见过太多人在 IDEA 里建 Servlet 时被各种细枝末节卡住——依赖版本对不上、找不到新建类的入口、启动 Tomcat 后访问 404、端口被占用报错……这些坑单个看不难但每一个都足够耗掉一个下午。这篇文章就把我从零开始用 IDEA 创建 Servlet 的完整流程整理出来从新建工程到配置 Tomcat再到写一个能真正响应请求的 Servlet按步骤照着走就能跑通。适用人群很明确刚接触 Java Web 的同学、被各种教程讲懵的转行者以及那些想从 Eclipse 切到 IDEA 的旧派玩家。这篇文章不铺垫过多理论重点在“能做出来”和“知道为什么这么做”你跟着敲一遍跑出第一个页面后面再学 Spring MVC、Spring Boot 都能少走不少弯路。1. 动手之前先把 Servlet 和这套开发链路想明白1.1 Servlet 到底是个什么角色Servlet 从字面上看是“服务器端小程序”本质就是一个运行在 Java 环境里的特殊类。它不像普通 Java 程序那样自己开端口、自己监听请求而是寄生在一个叫做“Servlet 容器”的宿主程序里——最常见的宿主就是 Tomcat。用餐厅来类比会直观很多浏览器是顾客Tomcat 是餐厅大堂Servlet 是服务员。顾客来点菜大堂经理Tomcat收下点单信息把需求转给对应的服务员Servlet服务员处理后把菜品HTML 响应内容端出来再由大堂交回给顾客。整个过程中Servlet 自身不直接面对浏览器它只做“接收参数、处理逻辑、输出响应”这三件事。理解这层关系后你就明白为什么教程里总说“Servlet 依赖于 Tomcat 才能运行”了。也正因如此你在 IDEA 里写 Servlet 时真正要做的事情其实只有三件写好这个特殊类的代码、告诉容器“哪个 URL 对应哪个 Servlet”、把工程打包后丢进容器跑起来。1.2 为什么用 IDEA Maven Tomcat 这套组合现在 Java Web 开发环境有很多种组合方式但我在教学和实际项目里最推荐 IDEA Maven Tomcat 三件套理由很简单IDEA 是当前 Java 开发者的主流主力它的智能提示、代码跳转、断点调试都相当顺手当你从原生 Servlet 阶段开始用 IDEA后面切到 Spring 系列框架时项目结构基本不用重新适应。Maven 解决的是依赖管理问题——Servlet API 不是一个你在电脑上手动下载 jar 包就能安心用的东西它最好通过 Maven 声明式引入由 Maven 自动下载和管理版本省去手工搬 jar 的麻烦。Tomcat 则是业界最常用的 Servlet 容器它体积小、配置直观、社区资料多对新手最友好。这套组合还有一个核心优势它贴近真实项目开发流程。许多企业的老旧系统至今仍是“SSH 重壳”或“SSM 框架 外部 Tomcat 部署”的模式你在 IDEA 里练熟这套工程结构和部署流程直接能迁移到工作场景中不会出现“教程跑得很顺进公司一脸懵”的情况。1.3 版本选型照着这套配少踩一半的坑版本不匹配是新人翻车的第一大原因。我建议按这个组合来配环境JDK 8 或更高版本Servlet 4.0 规范最低要求 Java 8JDK 8 本身的长期支持特性也足够日常使用。IDEA 2021.1 之后的版本新版对 Maven 和 Tomcat 集成都更完善操作界面和本文描述更接近。Maven 3.6Maven 3.8 以上在使用上没什么障碍老版本也不影响。Tomcat 8.5 或 9.0这两个版本分别对应 Servlet 3.1 和 4.0 规范兼容性最稳。注意虽然 Servlet 5.0/6.0 规范已经发布对应的是 Jakarta EE 命名空间但大量教材和公司老项目仍在使用 javax.servlet 包。初次学习阶段先在 Tomcat 8.5 javax 环境下跑通最有价值等基础牢固后再迁移到新规范也不迟。2. 环境准备先花十分钟检查和补齐工具2.1 你需要准备的东西开始写代码前先把下面四样东西装好JDK建议 8 或 11安装后配置JAVA_HOME环境变量。IDEA社区版Community和旗舰版Ultimate都行但对 Tomcat 集成的支持有差异这点我下面会专门说明。Maven不用单独装也行IDEA 自带了一个 Maven但建议自己装一个并把 IDEA 的 Maven 路径指到本地安装目录这样可控性更高。Tomcat去官网下载zip版解压即可无需安装。解压后目录里能看到bin、conf、webapps等文件夹这就是一个完整的容器了。2.2 确认环境可用的三个动作打开终端依次执行下面三条命令确认环境无误java -version mvn -vn echo %CATALINA_HOME%java -version能看到 java 版本mvn -vn能看到 Maven 版本CATALINA_HOME是 Tomcat 的环境变量某些老版本教程会要求配置它但用 IDEA 集成启动时其实不强制。你只要保证前两条命令有输出即可。2.3 IDEA 社区版和旗舰版的最大差异这里必须多说一句。IDEA 社区版免费版默认不带 Tomcat 集成功能你在运行配置里加号下拉根本找不到 “Tomcat Server” 选项。很多新手在这个位置放弃或者以为是电脑问题其实只是用错了版本。旗舰版则原生支持 Tomcat 集成直接在配置界面里指定 Tomcat 目录就能启动。社区版使用者也不用慌装一个叫Smart Tomcat的插件IDEA 插件市场直接搜就能实现同等的启动、停止、部署功能。后面第 3 章实操部分我将以旗舰版的方式为例讲述社区版用户装好插件后操作路径也大同小异。3. 创建 Servlet 的完整实操流程跟着做就能跑通3.1 第一步新建 Maven Web 工程打开 IDEA 后按File - New - Project左侧选择Maven然后勾选Create from archetype。这里的 archetype 可以理解为“项目模板”我们选择maven-archetype-webapp它就是 Maven 官方提供的 Web 工程骨架。如果下拉列表里找不到这个 archetype点击旁边的Add Archetype手动填入三要素GroupId 填org.apache.maven.archetypesArtifactId 填maven-archetype-webappVersion 填1.4。填完点 OK再选中它创建项目。接着填写项目基本信息GroupId组织名一般用域名反写比如com.example。ArtifactId项目名比如servlet-demo。Name一般保持和 ArtifactId 一致。点 Next 直到 FinishIDEA 会联网下载 archetype 模板新建出的工程目录大概长这样servlet-demo/ ├── pom.xml └── src/ └── main/ ├── resources/ └── webapp/ ├── WEB-INF/ │ └── web.xml └── index.jsp这里有一个必须手动处理的坑这个模板默认不会帮你建java源码目录。你需要右键src/main选择New - Directory命名为java。创建完成后右键java目录选Mark Directory as - Sources Root。这一步决定了你后面能不能在里面创建 Java 类忘了标记的话IDEA 不会把该目录当源码根类会显示成普通文件夹。3.2 第二步补齐 pom.xml 中的依赖和编译配置打开工程根目录下的pom.xml在dependencies标签中加入 Servlet API 依赖。dependencies dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency /dependencies为什么要加scopeprovided/scope因为 Tomcat 容器里已经自带了 Servlet API 的实现类如果我们把依赖以默认的compile方式打包进war包部署时就会出现类冲突甚至直接抛LinkageError之类的异常。provided的意思是“编译期我需要你运行期容器提供你”这样打包时不会重复打入。顺手建议在pom.xml里配置一下编译版本避免默认编译级别过低导致语法识别异常properties maven.compiler.source8/maven.compiler.source maven.compiler.target8/maven.compiler.target /properties右键工程名选择Maven - Reload ProjectIDEA 就会根据 pom 文件下载依赖。第一次下载会慢些尽量在网络稳定的时间段操作。3.3 第三步编写第一个 Servlet 类在src/main/java下新建包比如com.example.servlet然后在包下新建一个 Java 类命名HelloServlet。类的内容可以直接参考下面这段package com.example.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; WebServlet(/hello) public class HelloServlet extends HttpServlet { Override public void init() throws ServletException { System.out.println(Servlet 初始化方法执行了); } Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(text/html;charsetUTF-8); PrintWriter out response.getWriter(); out.println(html); out.println(headtitle第一个 Servlet/title/head); out.println(body); out.println(h1Hello, Servlet 欢迎你/h1); out.println(p当前时间 new java.util.Date() /p); out.println(/body); out.println(/html); out.close(); } Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }这段代码里的几个关键点继承 HttpServlet所有 Servlet 类要么实现 Servlet 接口要么继承 HttpServlet 这个便捷基类。日常开发 99% 都是继承 HttpServlet因为它把 GET、POST、PUT 等请求方法帮你分好了你只需要重写对应的方法即可。重写 doGet 而不是 service容器收到 GET 请求后会调用 service 方法而 HttpServlet 的 service 会自动根据请求方法路由到对应的 doXxx 方法。我们不直接重写 service而是重写 doGet这样代码更清晰也符合开发习惯。doGet 里的读取请求与写入响应HttpServletRequest request封装了浏览器传来的所有信息比如参数、请求头、路径HttpServletResponse response是用来写返回内容的对象。setContentType声明返回的文本类型和编码PrintWriter则是把 HTML 字符串写回浏览器的通道。doPost 调 doGet表单提交常用 POST我们这里简化处理让 POST 和 GET 走同一套逻辑方便后面测试。3.4 第四步配置 URL 映射的两种方式Servlet 不像普通 Java 类那样有main方法可以直接运行它必须和某个 URL 地址“绑定”容器才知道访问哪个路径时调用哪个类。这个绑定叫映射有两种实现方式。方式一注解配置推荐在上面代码中WebServlet(/hello)这行注解就是映射配置。/hello就是访问路径注意必须用/开头。使用注解方式时可以完全不管 web.xml 里的 servlet 配置代码更简洁也是 Servlet 3.0 规范之后的推荐做法。方式二web.xml 配置传统方式如果你查看src/main/webapp/WEB-INF/web.xml里面是一个模板骨架。传统方式是在这个文件里手动声明 Servlet 和映射关系servlet servlet-nameHelloServlet/servlet-name servlet-classcom.example.servlet.HelloServlet/servlet-class /servlet servlet-mapping servlet-nameHelloServlet/servlet-name url-pattern/hello/url-pattern /servlet-mapping这里必须提醒一个关键坑如果你在类上加了WebServlet(/hello)又在 web.xml 里配了同样的映射启动时 Tomcat 会直接报错提示重复映射。两者选其一即可初学者我强烈建议用注解少一处配置就少一处出错。3.5 第五步配置 Tomcat 并部署运行现在到了最容易让人兴奋也最容易翻车的环节。以 IDEA 旗舰版为例点击运行配置下拉框选Edit Configurations。点左上角选择Tomcat Server - Local。在Application server处点击Configure选择你本地 Tomcat 的解压目录。切到Deployment标签页点选Artifact会看到类似servlet-demo:war exploded的选项选中添加。Application context默认是servlet-demo你可以改成/。这个值代表项目访问的根路径改成/后访问时就不用再带项目名。点击OK保存配置然后点运行按钮启动 Tomcat。启动后IDEA 下方的控制台会刷出 Tomcat 的启动日志耐心等几秒看到Server startup in [xxx] milliseconds就说明启动成功了。此时打开浏览器访问http://localhost:8080/hello如果一切正常你会看到自己写的 HTML 内容页面上显示当前时间。如果你用的是社区版则先安装 Smart Tomcat 插件在Edit Configurations里添加Smart Tomcat指定 Tomcat Server 路径、部署的工程路径和 Context Path启动效果与旗舰版基本一致。4. 核心原理拆解为什么请求能到达你的 Servlet4.1 一次完整的请求之旅浏览器地址栏输入http://localhost:8080/hello后到底发生了什么把这个链路想清楚后面所有 Web 框架你都能举一反三。浏览器向本机8080端口发起 HTTP 请求请求行中带有路径/hello。Tomcat 作为容器一直在监听8080端口收到这个请求后会解析出 URL 中的路径部分。Tomcat 根据WebServlet(/hello)的映射关系在已加载的 Servlet 中定位到HelloServlet这个类。容器创建本次请求专属的HttpServletRequest对象和HttpServletResponse对象并调用HelloServlet的service方法。HttpServlet父类的service方法根据请求方法GET/POST自动调用我们重写的doGet或doPost。我们在doGet里通过response.getWriter()写出的 HTML 字符串会由 Tomcat 从响应对象中取走封装成 HTTP 响应报文。浏览器拿到响应报文后解析 HTML渲染成页面展示给用户。这就是为什么你在 Servlet 代码里能直接访问request参数、能随手把内容写进response——这两个对象不是你自己 new 出来的而是容器为每一次请求临时创建的。它们的生命周期和周而复始构成了整个 Web 交互的基础。4.2 Servlet 的生命周期三个阶段一次看完在一个 Servlet 从出生到销毁的过程中有三个方法扮演着关键角色init()第一次访问该 Servlet 时容器会创建它的实例并调用init进行初始化。init在整个生命周期里只执行一次。适合做数据源连接、配置加载等一次性操作。service()/doGet()/doPost()每次请求进来容器都会调用对应的方法。这个方法会被并发调用因此不要在 Servlet 成员变量中随意存请求相关的可变数据。destroy()容器关闭或卸载该应用时会调用destroy进行资源清理整个生命周期结束。你可以把init理解成餐厅开业前的后厨准备——只做一次doGet是每一次被叫到号时的工作过程——反复执行destroy是打烊后的清理工作——最后做一次。为了直观验证这个流程把刚才代码里的System.out.println打开启动 Tomcat 后第一次访问/hello控制台会打印出初始化方法执行的字样刷新页面不会再次打印初始化停止 Tomcat 时则可能看到 destroy 相关输出需要在类里额外重写 destroy 方法才会看到。这个实验强烈建议做一次做完你对 Servlet 生命周期就彻底有底了。4.3 URL 映射规则与路径组合的细节访问 Servlet 的完整路径由两部分组成项目上下文路径 Servlet 映射路径。如果Application context设为/那么访问路径直接就是http://localhost:8080/hello。如果Application context保持默认的servlet-demo那么完整访问路径就是http://localhost:8080/servlet-demo/hello。很多人在这个环节 404就是搞混了这两段路径的拼接方式。记住一个口诀上下文路径配在容器部署里映射路径写在注解或 web.xml 里浏览器访问时把两者顺序拼起来。另外映射路径也支持模糊匹配比如WebServlet(/user/*)可以同时匹配/user/list、/user/detail等地址但初学者先用精确匹配就好模糊匹配容易把访问范围搞大反而不利于排查问题。5. 常见问题与排查技巧实录5.1 快速对照表遇到问题先看这张表下面这些是我在教学和实战中遇到频率最高的几个问题整理成速查表遇到报错先对照排查能省大量时间。现象最可能的原因解决办法访问http://localhost:8080/hello显示 404URL 路径拼错或映射路径不一致核对Application context和WebServlet值是否拼对Tomcat 启动时端口被占用8080 端口已被其他进程占用关闭占用进程或修改 Tomcat 的server.xml端口号IDEA 控制台中文乱码JDK 或 Tomcat 默认编码不是 UTF-8在运行配置的 VM options 中加-Dfile.encodingUTF-8启动时报A child container failed during start()Tomcat 版本和 Servlet 依赖版本冲突换成 Tomcat 8.5/9.0 javax.servlet-api 4.0.1Servlet 类写了但运行时报 404类没有编译进部署产物确认java目录已标记为 Sources Root重新部署页面中文内容乱码响应编码未设置在代码里调用response.setContentType(text/html;charsetUTF-8)5.2 三个必看的排查细节排查一区分 404 和 500404 表示找不到资源问题大多出在路径上——映射错了、上下文路径不对、部署产物没生成500 表示服务器内部异常问题大多出在代码上——空指针、类找不到、依赖冲突。看到 500 别急着改路径去 Tomcat 日志里翻异常堆栈一找一个准。排查二部署列表里没有可用 Artifact在配置 Deployment 时如果Artifact列表是空的说明工程缺少 Web 构件定义。右键工程名选择Open Module Settings在Facets里点击先添加Web再在Artifacts里点击选择Web Application: Exploded把 Web 目录指向src/main/webapp重复上面的添加步骤即可解决。排查三Tomcat 启动后访问返回 404但日志显示 Started这种情况最迷惑人。其实 “Started” 只表示容器启动成功不代表你的应用一定部署成功。你需要观察启动日志中是否有Deploying web application directory、Deployment of web application archive之类的行。如果没有部署记录多半是部署配置不正确重新检查 Deployment 里的 Artifact 是否添加成功、Application context 是否设置合理。5.3 独家避坑开发阶段的小技巧我个人的习惯是开发阶段一定用war exploded部署而不是打 war 包。exploded 部署相当于把解压后的目录直接扔给 Tomcat修改类或静态资源后容器的热重载机制能更快地感知变化省去反复打包的沉闷等待。配合 IDEA 的运行配置里的 “Build project automatically” 选项能让开发节奏顺畅很多。另一个小技巧是在 IDEA 中给 Tomcat 运行配置的VM options里加上一句-Dfile.encodingUTF-8这能解决控制台输出、日志和编码相关的一大部分乱问题。很多人以为乱码是代码问题折腾半天其实只是 JVM 启动参数没配 UTF-8。最后分享一点我的体会说句心里话Servlet 技术本身已经是 Java Web 体系里最古老的环节之一了现在新项目基本都直接用 Spring Boot 内嵌容器开发。但我依然建议所有入行 Java Web 的人老老实实亲手建一次 Servlet 工程、写一遍 doGet、配一次 Tomcat。因为后面框架里那些看似神奇的功能——请求路由、参数绑定、响应封装本质都是在 Servlet 规范之上做的封装。你把 Servlet 的请求、响应、映射、生命周期这四件事弄明白了学 Spring MVC 时你会发现新世界的大门是敞开的。我个人在实际操作中最受益的一个习惯是在跑通第一个 Servlet 后主动做一个小扩展写一个LoginServlet模拟表单提交用request.getParameter(username)读取参数再让页面显示“欢迎 xxx”。这个小练习能把doPost、表单提交、请求参数读取这几个核心点全部串起来做一次比看十遍教程都有用。最后再留一个延伸方向在你已经跑通的servlet-demo项目里试着通过 JSP 页面发送表单请求路径指向刚才的HelloServlet再用request.getParameter(name)动态拼接 HTML。这一步做完你的 Java Web 基础就算真正筑基成功了。
延伸阅读

更多相关文章

2026/10/20 13:49:09

人工势场法船舶避障:模型构建、参数调优与问题排查

1. 人工势场法到底在解决什么问题1.1 从机器人到船舶:同一套算法为什么换了玩法做机器人避障时,我第一次接触人工势场法,觉得这算法的思路简单得有点“可爱”:目标点在前面拉,障碍物在旁边推,路径自然就出来…

2026/10/20 13:49:09

Java复制远程共享文件夹:基于SMBJ的完整实现与优化

1. 残缺标题背后的完整需求:本质上是一趟SMB文件搬家我猜很多人在搜索引擎里敲下“Java 复制远程共享文件夹到”这半句话时,后面想接的往往是“本地”“服务器目录”或者“另一个共享目录”。虽然标题看着缺了半截,但需求其实非常明确&#x…

2026/10/20 13:49:09

信奥赛NOIP考点分布与刷题攻略:高频模板+易错点全解

简介:信息学奥赛(NOIP)作为中学生算法竞赛的核心入口,以C为语言载体,重点考察算法与数据结构的代码实现能力。其考点分布相对稳定:基础算法占比最高,动态规划与图论搜索紧随其后,理解…

2026/10/20 15:04:58

sqli-labs第11-45关实战:POST注入、宽字节与堆叠注入全解析

sqli-labs是我见过最适合练SQL注入手感的靶场,没有之一。它不像某些综合漏洞环境那样追求大而全,而是把每一种注入类型拆成一课一课的关卡,从最简单的GET单引号注入,一路做到二次注入、宽字节、堆叠,难度曲线非常平滑。…

2026/10/20 15:04:58

基于DB37T 5200-2021的市政工程安全文明施工资料台账体系搭建指南

简介:这份《DB37T 5200-2021 市政工程安全文明施工资料管理》PDF文档,面向市政工程施工单位的技术负责人、安全员、资料员及监理人员,用于解决施工过程中安全、文明与资料三大板块管理标准不统一、归档不规范的问题。资源包共1个PDF文件&…

2026/10/20 15:04:58

STM32F407 ADC采样与DMA搬运实现FFT频谱分析完整方案

简介:面向STM32嵌入式开发者的ADC采集与FFT频谱分析工程参考,基于STM32F407内置ADC,通过定时器触发、DMA搬运实现输入电压连续采样,支持512kHz、256kHz、128kHz三档采样频率切换,并将FFT运算结果经串口实时打印输出&am…

2026/10/20 15:04:58

Open WebUI实战:用Docker容器化部署接入Ollama完整教程

Open WebUI 是我最近这半年用得最顺手的大模型交互工具,没有之一。如果你已经在本地跑过 Ollama 或者其他推理框架,大概率会有同感:模型确实强,但每次想对话都要在终端敲命令或者在 Hugging Face 页面上一顿操作,总感觉…

2026/10/20 15:04:58

Open WebUI部署实战:从Docker到Ollama的图形化大模型交互指南

如果你手里已经有一台能跑模型的机器,那你大概率已经被命令行交互折磨过——模型跑起来了,但对话体验基本等于在终端里打字,没有上下文管理,没有Markdown渲染,没有历史记录,更别说支持多人共用。这就是Open…

2026/10/20 14:59:56

x11vnc配置指南:Ubuntu远程桌面共享真实屏幕

1. 需求梳理:从一台Ubuntu到另一台电脑的远程桌面如果你和我一样,平时的主力机器装的是 Ubuntu 桌面版,难免会遇到“人不在机器旁边,却想直接操作这台机器桌面”的时刻。我第一次被逼着去折腾 Ubuntu 远程桌面配置,是因…

2026/10/19 18:06:35

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/20 1:05:37

单片机C运行时从启动到多任务:中断安全与共享资源冲突

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:05:37

GCC编译四步详解:预处理、编译、汇编、链接实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:05:37

FIW线是什么?FEP注塑线与普通氟塑料线的区别及应用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑