news 2026/10/11 2:28:27

IDEA 2024 配置 Tomcat 与 Servlet 全攻略:从版本选型到部署运行

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
IDEA 2024 配置 Tomcat 与 Servlet 全攻略:从版本选型到部署运行

第一次接触 Tomcat 和 Servlet,很多人都会在 IDEA 里兜圈子:代码明明照着写了,点运行却跳出 404;或者明明用的是老教程,放进新版 IDEA 却直接编译失败。 这类事情我前前后后折腾过很多回,每次帮朋友排查最后几乎都会落到同一个原因:IDEA 2024 这个版本,默认环境和老的 Tomcat 9 + javax.servlet 教程完全是两套逻辑。 如果你也卡在“部署完访问不到”“Servlet 找不到类”这一步,这篇应该能帮你把从建项目到配服务器的整条路走通一遍。

这篇内容适合刚学 Java Web、第一次用 IDEA 建动态 Web 项目、或者以前用过 Eclipse / 老版本 IDEA 想切到最新版的人。我会把版本选型、建项目、写 Servlet、连 Tomcat、部署运行、报错排查这几个环节串在一篇文章里写好,重点说清楚为什么这么做,而不只是给一串点击步骤。

1. 环境准备与版本选型,这一步错了后面全白搭

1.1 为什么 IDEA 2024 里的坑和以前不一样

用 IDEA 2024 和网上大量旧教程碰到的最大的差异,出在 Servlet API 的命名空间上。 Tomcat 9 及更早版本用的是javax.servlet,但从 Tomcat 10 开始,官方把包名改成了jakarta.servlet。IDEA 2024 新建项目时默认引用的组件、以及你手工下载当前版 Tomcat 时拿到的几乎都是 Tomcat 10.1 或更高版本,于是老代码里的import javax.servlet.http.HttpServlet就会直接标红,或者在部署时抛NoClassDefFoundError。

我实际推荐两种最稳妥的组合,二选一:

组合JDKTomcat 版本Servlet 依赖包名适用场景
保守方案JDK 8 或 JDK 11Tomcat 9.xjavax.servlet-api跟着老教材学,公司老项目维护
主流方案JDK 17Tomcat 10.1.xjakarta.servlet-apiIDEA 2024 默认环境,推荐新手

我自己现在默认走的是第二种,也就是 JDK 17 + Tomcat 10.1 +jakarta.servlet-api。不是因为它比老的先进多少,而是 IDEA 2024 对这套组合识别得最顺,Maven 创建项目时不会因为包名不一致报一堆红线。如果你手头已经有 Tomcat 9,那把依赖换成javax.servlet-api也完全没问题,下面的步骤全部通用,只有 import 的包名前缀不一样。

1.2 JDK 与 Tomcat 到底要不要配环境变量

很多教程第一步就让你去系统里设置JAVA_HOME和CATALINA_HOME。如果你只是在 IDEA 里跑本地开发,这一步我建议跳过,不要配。 IDEA 自己会识别它内置的 JBR 运行时,也可以直接用你在 Project Structure 里指定的 JDK,不需要在系统层面做任何干预。 反倒是你手动改了全局环境变量,很可能和 IDEA 自带的 JDK 版本冲突,出现“IDEA 里能编译,命令行启动 Tomcat 却报版本错误”的怪问题。

真正要用到的,是你在创建项目时,Project SDK 明确选择成你安装的 JDK,然后在 Tomcat 的配置界面里确认所选 JDK 和项目一致。这比设什么环境变量都实在。

如果你一定要在命令行里验证一下环境,可以执行下面两条命令,看到版本号就说明没问题:

java -version

Tomcat 本身也不需要手动设置 CATALINA_HOME,IDEA 配置 Tomcat Server 的时候,只需要指定 Tomcat 安装目录,它自己会去找里面的bin/catalina.bat。

2. 在 IDEA 2024 里创建 Web 工程,别用错了模板

2.1 为什么优先用 Maven 生成项目

我见过不少朋友建 Java Web 项目是直接在 IDEA 里选Java Enterprise或者手动创建目录再补web文件夹。不是说不能用,而是 IDEA 2024 里新建 Maven 项目最省事,依赖管理清晰,打包 war 也简单,后面部署的时候能少踩一堆坑。 Maven 会帮你自动建出标准的src/main/java、src/main/resources和src/main/webapp结构,你不用自己记哪里该放代码、哪里该放页面。

实际操作流程是:

  1. 打开 IDEA,选择New Project,左侧选Generators里的Maven。
  2. 设置好项目名。Project SDK 选 JDK 17。
  3. 不要勾选模板里的任何骨架(比如maven-archetype-webapp),IDEA 2024 生成的普通 Maven 项目反而够干净。
  4. 创建完成后,手工在src/main下新建webapp目录,这就是之后放 JSP、HTML、静态资源的地方。

这样得到的项目结构如下:

项目根目录 ├── pom.xml └── src └── main ├── java ├── resources └── webapp

如果你已经建好了一个 Maven 项目,也不用推翻重来,直接在 Project Structure 里给模块添加一个 Web Facet,再把 Web Resource Directory 指向src/main/webapp,效果一样。只是对新手而言,直接在创建时规划好更不容易漏。

2.2 pom.xml 里的 Servlet 依赖,照着抄也得看版本

建好 Maven 项目后,第一件事是把pom.xml里的依赖加上。下面这段是 Tomcat 10.1 对应的 Servlet 6.0 依赖:

<dependencies> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency> </dependencies>

如果你用的是 Tomcat 9,把这段换成:

<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency>

这里的<scope>provided</scope>很关键。它的意思是编译的时候用这份依赖,但最后打成 war 包时不要把它打进去。因为 Tomcat 自己本来就带了一套 Servlet 实现,你再塞一份进去,启动时反而可能因为 jar 包冲突报各种奇怪错误。 不少新手就是漏了这一步,部署后 Tomcat 一启动就报ClassCastException或者LinkageError,原因就是 lib 里放了多份 Servlet API。

2.3 约定优于配置:用 @WebServlet 注解代替 web.xml

以前写 Servlet 都要在web.xml里手动配置<servlet>和<servlet-mapping>,一个类一行配置,类一多就长到没法看。Servlet 3.0 之后引入了注解@WebServlet,可以直接写在类上,省掉 web.xml 的重复劳动。

IDEA 2024 里新建项目默认是支持注解扫描的,所以你只需要在类上写好 URL 映射,不用再手动维护 web.xml。我这里明确一点:只要你没在项目中创建web.xml,Tomcat 就会自动扫描@WebServlet; 如果你保留了 web.xml,而且里面连 content 版本都没写对,反而可能拦截扫描,导致你的注解不生效。 这个细节我栽过一次:项目里有个历史遗留的空 web.xml,结果加了注解的新 Servlet 怎么访问都是 404,最后把 web.xml 删掉就好了。

3. 第一个 Servlet:从写代码到请求被正确处理

3.1 用代码理解 Servlet 生命周期

Servlet 说白了就是一个能处理 HTTP 请求的 Java 类。它本身没有 main 方法,Tomcat 负责创建它的实例,并在合适的时机调用它的init、service、destroy这些方法。 你可以把它理解成 Tomcat 给你提供的服务员模板,你负责写清楚“收到请求后该干什么”,Tomcat 负责把客人领到你面前。

一个最小可用的 Servlet 长这样:

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("/hello") public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().write("<h1>Hello, Servlet!</h1>"); } }

新建类的时候,注意jakarta.servlet开头,确认和 pom 里的依赖一致。写完这个类之后,Maven 会自动编译,IDEA 里如果没有红线,就可以进入部署环节了。

3.2 GET 和 POST 请求的分流处理

HttpServlet父类已经在底层帮你做好了service方法的路由:根据 HTTP 请求的 method 自动调doGet或doPost。你在子类里重写哪个方法,就代表处理哪种请求。

一个最典型的场景,浏览器直接在地址栏输入 URL 访问是 GET,表单直接提交也是 GET。而用 POST 提交一般是为了传数据,比如登录、注册、上传。 新手容易犯的错是 HTML 表单设置了method="post",后端却只写了doGet,结果点击提交后收到的要么是 405 错误,要么是空白页。

建议你一上来就把两个方法都写上,哪怕是先写在同一套处理逻辑里:

@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { process(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { process(req, resp); } private void process(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/html;charset=UTF-8"); String name = req.getParameter("name"); resp.getWriter().write("收到的 name 是:" + name); }

这样不管 GET 还是 POST 都能跑到同一个业务方法,排查问题范围更小,也不容易因为方法漏写出现 405。

3.3 请求参数怎么拿,响应中文怎么不乱码

拿到 URL 里的参数,通常用req.getParameter("参数名"),这个方法同时兼容 GET 的 query string 和 POST 的 form body。 但如果你用 POST 提交中文,不设置编码,很容易出现乱码。正确做法是在读取任何参数之前先设置:

req.setCharacterEncoding("UTF-8");

响应的中文乱码则是另一回事,必须设置响应类型,也就是resp.setContentType("text/html;charset=UTF-8")。我见过有人只在 resp 里设置了编码,却在 req 里忘了设置,导致“请求中文乱,响应中文正常”的情况。 两个地方都要设置,不要偷懒只写一处。

下表可以当成速查:

情况设置位置代码
表单提交中文变乱码读取参数前req.setCharacterEncoding("UTF-8")
页面输出中文变乱码获取 Writer 前resp.setContentType("text/html;charset=UTF-8")

4. 在 IDEA 2024 里连接 Tomcat 并启动部署

4.1 配置 Tomcat Server 的完整路径

写好了代码,接下来就是把项目“接”到 Tomcat 上跑起来。IDEA 里这一步叫Run/Debug Configurations,快捷键可以直接用右上角的服务器下拉框,选Edit Configurations。

点击左上角加号,找到Tomcat Server -> Local。如果你是第一次配置,IDEA 会要求你指定Tomcat Home或者Application server路径,直接选到你解压 Tomcat 的目录,比如D:\apache-tomcat-10.1.28。IDEA 会自动识别版本。

这里有一个重点:新添加的配置里面不会帮你自动部署项目。你必须在Deployment选项卡里加一个 Artifact,否则运行的时候 Tomcat 是起来了,但访问你的项目路径只会看到 Tomcat 的默认首页或者 404。

4.2 选择 war 还是 war exploded

在 Deployment 选项卡里点击加号,Artifact下通常会出现两个选择:项目名:war和项目名:war exploded。

  • war:把整个项目打包成一个 war 文件,再复制到 Tomcat 的 webapps 目录下解压运行。它更接近真实部署,但修改代码后需要重新打包,速度慢。
  • war exploded:把项目按解压后的目录结构直接当作 Web 应用来跑,修改静态页面和 Java 代码后经常能实现热更新,开发时更方便。

我本地开发一律选war exploded,迭代速度快很多。 尤其是你改一个 JSP 或者静态资源,有时候连重启都不用,刷新页面就能看到效果。

添加好后,下面会有一个Application context输入框,默认是/项目名。 这个路径决定了你访问应用的前缀,比如项目名是demo,那你访问的完整地址就是:

http://localhost:8080/demo/hello

前缀路径经常是新手找不到 Servlet 的主要原因:只记得/hello,忘了前面还要带/项目名。 你把它改成/也可以,这样访问时就变成http://localhost:8080/hello,但一般不建议,因为一个 Tomcat 实例跑多个项目时容易冲突。

4.3 运行前检查端口和 provided 依赖

配置好之后,一般不建议直接点运行,先检查三件事:

  1. Tomcat 默认端口是不是 8080,是否已经被占用。 如果 8080 被别的进程占用了,有两个办法:换端口,或者杀掉占用进程。换端口最快,在Server选项卡里找到HTTP port,改成8081。杀占用进程的办法我放在后面常见问题里写。
  2. 部署项目的 URL 路径里有没有 application context。
  3. 确认 pom 里的 Servlet 依赖 scope 还是 provided。 如果之前误写成了 compile,运行后很可能在 Tomcat 的 lib 下出现重复的 Servlet jar。

点运行之后,IDEA 下方会跳出一个 Tomcat 的日志窗口。看到类似下面的日志,就说明启动成功了:

Server startup in [xxx] milliseconds

这时候打开浏览器,访问 http://localhost:8080/demo/hello ,如果页面出现“Hello, Servlet!”,第一个 Servlet 就跑通了。 如果没出来,也别急着改代码,先去看日志里的关键字,绝大部分问题都能在日志里找到答案。

5. 运行阶段的常见报错与排查思路

5.1 访问 404,先区分是哪个层级的 404

看到 404 是最容易慌的,但其实只要分清“Tomcat 都起来了,只是应用没找到”和“应用找到了,Servlet 路径没匹配上”这两种情况,处理起来就清晰了。

先访问http://localhost:8080,如果能看到 Tomcat 默认首页,说明服务器本身没问题。再访问http://localhost:8080/demo/,如果能出现项目下的 index.jsp 或目录列表,说明项目部署成功,问题在 Servlet 的路径映射上。 如果连/demo/都 404,那就是 Deployment 的 Application context 和你输入的路径不一致,或者 Artifact 没有正确添加。

常见对应关系如下:

访问结果大概原因处理方向
8080 正常,/demo404应用没部署或 context 对不上检查 Deployment 里的 Artifact 和 Application context
/demo正常,/demo/hello404注解映射路径不对检查@WebServlet("/hello")是否写成/hello.do或漏了斜杠
所有路径都 404 且日志无异常web.xml 干扰了注解扫描删除或清空 web.xml

5.2 500 和 NoClassDefFoundError,多半是包名或依赖冲突

如果你启动时报的是NoClassDefFoundError: javax/servlet/...,那么原因基本可以锁定为:你用的 Tomcat 是 10 以上版本,但代码里引用的是javax.servlet。 反过来,如果你用的 Tomcat 9,但依赖引的是jakarta.servlet,同样地址找不到类。

遇到这个,别去改代码硬凑,先确认组合是不是一致。 简单判断方式就是看 import 语句的前缀:

  • Tomcat 10.1 +jakarta.servlet.http.HttpServlet
  • Tomcat 9 +javax.servlet.http.HttpServlet

两个前缀混用,就会出现编译时好好的、运行时发现 Tomcat 的类加载器里根本没有对应类的情况。 这类错误日志通常会显示Caused by: java.lang.ClassNotFoundException,顺着 Caused by 看最快。

5.3 端口被占用,怎么快速定位和释放

IDEA 启动 Tomcat 时经常报这样的错误:

Port 8080 was already in use. Tomcat cannot be started.

原因大概率是你之前启动过另一个 Tomcat 实例没关干净,或者别的程序占了 8080。 在命令行里执行下面两条命令,就能查到谁在用这个端口:

netstat -ano | findstr 8080

找到 PID 后,用任务管理器结束对应进程,或者用命令:

taskkill /pid 进程号 /f

如果你还在用 Mac 或 Linux,可以用lsof -i:8080查看,然后用kill -9 进程号结束。 要是你不想跟别人抢端口,省事的办法是在 Tomcat 配置里把 HTTP port 改成 8081,重启就行。 我自己的习惯是,如果这个端口以后要跑别的服务,就先找出进程杀掉;如果是自己本地练习,直接换端口也不丢人。

5.4 改了代码却看不到效果,多半是热部署没生效

IDEA 的war exploded虽然支持热部署,但默认设置不一定开全。 如果你改了 Servlet 代码后,重新请求还是旧结果,先看控制台有没有重新编译的日志。 如果没动静,可以手动在Build -> Rebuild Project强制重新编译一下,再访问页面。

如果你想尽量接近“改完就生效”,可以在这个运行配置的Server选项卡里,把On frame deactivation设置成Update classes and resources。 这样你从 IDEA 切回浏览器时,IDEA 会自动把更新的 class 和静态资源同步到 Tomcat 的部署目录。 不过改类名、改方法签名这类结构级改动,还是建议直接重启 Tomcat,因为热部署遇到类结构变化时容易出现内存里残留旧类,行为变得诡异。

个人经验是:页面样式、JSP、简单的返回值改动,交给热部署没问题;一旦要加变量、改函数签名,果断重启,省下的时间比等热部署出问题后再排查多得多。

写到这里,最基本的 Tomcat 部署和第一个 Servlet 应该能跑通了。再顺手补充一个我常用的习惯:每次启动前看日志的时候,别只盯着红色 ERROR 那几行,重点是Caused by后面跟的内容。 很多新手喜欢只看最上面的红色段落,结果问题根源在日志中间,一看日志长度就放弃了。 Tomcat 给的报错其实已经一步步把原因写在里面了,顺着Caused by逐层往下,基本都能找到真正的问题出在哪个 jar、哪个类、哪一行。

另外,后续如果你想接着往下扩展,可以顺手在同一个项目里加几个普通的 HTML 页面,再试着用表单 POST 到同一个 Servlet,体验一下 GET/POST 的分发逻辑。第一次可以慢点来,但把日志和请求路径看明白,后面加拦截器、过滤器、数据库连接的时候,就会顺很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/11 2:27:41

C# WinForms自绘漂亮登录窗体:无边框、圆角渐变与交互细节

简介&#xff1a;这份C#登录窗体资源是一套可直接参考的WinForms登录界面项目&#xff0c;面向桌面应用入门开发者及需要快速搭建账号登录模块的C#程序员。压缩包共70个文件&#xff0c;大小约550KB&#xff1b;11个.cs源文件配合4个.resx资源描述构成主工程核心&#xff0c;3个…

作者头像 李华
网站建设 2026/10/11 2:27:15

SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0全栈服装商城系统实战解析

搞Java Web电商类的项目&#xff0c;这两年最常见的需求就是“给我一个能跑、能看、能交差的全栈商城”。而网上服装商城这类带业务闭环的项目&#xff0c;正好是面试和毕设里出镜率最高的一种。今天这篇&#xff0c;我打算把手头这套SpringBoot2 Vue3 MyBatis-Plus MySQL8.…

作者头像 李华
网站建设 2026/10/11 2:26:00

告别鼠标:系统整理高效快捷键思维与实操技巧

你们有没有遇到过这种场面&#xff1a;旁边同事噼里啪啦一顿操作&#xff0c;窗口切换、文件另存、表格求和&#xff0c;鼠标基本不碰&#xff0c;几分钟搞定你磨蹭半小时的活儿。你不好意思问&#xff0c;只能默默盯着屏幕&#xff0c;心想这人是不是开了什么外挂。其实没啥神…

作者头像 李华
网站建设 2026/10/11 2:25:48

从闭环原理到故障排查:汽车传感器与执行器核心要点

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

作者头像 李华
网站建设 2026/10/11 2:25:11

室内场景实例分割数据集:从压缩包到YOLO训练管线的实战指南

简介&#xff1a;这份室内场景实例分割数据集面向计算机视觉开发者、机器人视觉研究者及高校师生&#xff0c;用于训练和评估能够精确分割室内家具与人物目标的AI模型。数据集共849张图片&#xff0c;按594张训练集、170张验证集、85张测试集划分&#xff0c;覆盖bench、chair、…

作者头像 李华