刚把 IDEA 升级到 2025 版本,准备新建一个 Servlet 项目跑通接口,结果在配置环节卡了整整一个下午。网上搜到的教程大多还停留在老版本的界面截图,菜单名字对不上,项目模板也变了,照着点半天根本找不到对应的选项。这篇文章把我踩过的坑和最终跑通的完整步骤整理出来,包括 IDEA 2025 的项目结构变化、Tomcat 的关联方式、Servlet 映射的两种写法,以及配置过程中最常见的报错排查思路。想在新版 IDEA 里把 Servlet 环境一次配好的同学,可以直接照着操作。
1. 配置前的环境准备:版本匹配是关键
1.1 JDK 版本选择与 Tomcat 的兼容关系
Servlet 不是独立运行的程序,它必须挂在 Servlet 容器里才能工作。最常见的容器就是 Tomcat。很多人配置失败,第一步就栽在版本匹配上——JDK 版本、Tomcat 版本、Servlet API 版本三者必须兼容,否则项目能启动,但页面永远报 500 或 ClassNotFoundException。
我用的组合是:
| 组件 | 版本 | 说明 |
|---|---|---|
| JDK | 17(LTS) | 长期支持版本,兼容 Jakarta EE 9+ |
| Tomcat | 10.1.x | 对应 Servlet 5.0 / Jakarta EE 9+ |
| IDEA | 2025.1(Ultimate) | 内置完整 Web 项目支持 |
这里有个非常容易踩的坑:如果你用的是 Tomcat 9 及以下版本,Servlet API 的包名是 javax.servlet.*;如果用的是 Tomcat 10 及以上版本,包名已经改成了 jakarta.servlet.*。这个变化是 Oracle 将 Java EE 捐给 Eclipse 基金会后发生的,很多老教程还在用 javax.servlet.http.HttpServlet,代码直接复制到 Tomcat 10 环境里编译都过不了。IDEA 2025 新建的 Web 项目默认面向 Jakarta EE,所以包名要用 jakarta.servlet.*,这点务必注意。
1.2 下载 Tomcat 并配置本地环境变量
去 Tomcat 官网下载 zip 压缩包(不要用安装版,解压即用最干净)。下载后解压到纯英文路径,比如 D:\apache-tomcat-10.1.32,路径里有中文或空格会导致 IDEA 识别异常。
理论上不配置环境变量也能用,因为 IDEA 可以直接指定 Tomcat 路径。但我建议还是把 CATALINA_HOME 配上,方便在命令行单独调试 Tomcat。配置方法是:右键"此电脑"→ 属性 → 高级系统设置 → 环境变量,新建系统变量:
code复制变量名:CATALINA_HOME
变量值:D:\apache-tomcat-10.1.32
同时在 Path 变量里追加 %CATALINA_HOME%\bin。配好后打开命令行,执行 catalina.bat version(Windows)或 catalina.sh version(macOS/Linux),能看到版本信息就说明配置成功。验证这一步很重要,它能排除 Tomcat 本身安装问题,避免后面 IDEA 报错时还要反过来排查 Tomcat。
1.3 确认 IDEA 2025 的版本类型
注意一点:Servlet 项目开发在 IntelliJ IDEA Community(社区版)里是受限的。社区版虽然能写 Java 代码,但默认不支持 Java EE Web 项目的新建和 Tomcat 集成,需要手动折腾插件或者用 Maven 骨架硬凑。如果你用的是社区版,强烈建议直接下载 Ultimate 版体验 30 天,或者用教育邮箱申请免费授权。IDEA 2025 的 Ultimate 版本把 Jakarta EE 项目模板、Tomcat 集成、Servlet 代码生成都做得非常顺滑,配置体验和社区版完全不是一回事。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 在 IDEA 2025 中创建 Servlet 项目的两种正确姿势
2.1 姿势一:使用内置项目模板
IDEA 2025 的 New Project 向导变化不小,之前的 "Java Enterprise" 选项现在整合到了左侧类别里。具体步骤:
- 打开 IDEA,点击
New Project。 - 左侧选择
Jakarta EE类别,右侧选择 Web 项目类型,比如 "Web Application"。 - 在 Application Server 区域点击
New,选择已经解压好的 Tomcat 10.1 路径。 - 语言选 Java,构建工具选 IntelliJ(也可以选 Maven,但我后面会解释为什么 IntelliJ 方式更简单)。
- 勾选 "Generate web.xml deployment descriptor",这样会生成
web.xml文件,方便后续配置 Servlet 映射。 - 点击 Finish 完成创建。
这个模板生成的项目结构如下:
code复制src/
└── main/
├── java/
└── webapp/
├── WEB-INF/
│ └── web.xml
└── index.jsp
注意:IDEA 2025 生成的项目里没有 src/main/resources 目录,这在纯 Servlet 阶段无所谓,反正也用不到配置文件。如果后面要整合 MyBatis 或 Spring,记得手动补上。
2.2 姿势二:手动创建 Maven Web 项目
如果你已经安装了 Maven,并且习惯用 Maven 管理依赖,也可以走手工创建这条路。选择 New Project → 左侧选 Maven,然后勾选 Create from archetype,选择 org.apache.maven.archetypes:maven-archetype-webapp 骨架。
这个骨架的步骤比较繁琐,而且国内网络访问中央仓库经常超时,IDEA 还需要额外配置 Maven 镜像源。我的建议是:如果只是学 Servlet,不涉及复杂依赖管理,直接用内置模板就够了,不要为了显得专业而引入 Maven。Maven 在 Servlet 阶段会带来很多无关的配置负担,等学到 SSM 框架再引入也不迟。
2.3 项目结构解析与核心目录作用
不管是哪种方式创建的项目,有几个目录的含义必须搞清楚:
src/main/java:存放 Servlet 类、过滤器、监听器等 Java 代码。src/main/webapp:存放 JSP、HTML、CSS、JS 等静态资源。这个目录就是 Web 应用的根目录,最终会被打成 WAR 包部署到 Tomcat。WEB-INF:这个目录比较特殊,对外部访问不可见。浏览器不能直接访问WEB-INF下的文件,但 Servlet 可以通过请求转发等方式间接访问。web.xml就放在这里,它是部署描述符,告诉容器哪些 URL 对应哪些 Servlet。
很多新手把 JSP 页面或者图片放在 WEB-INF 目录下面,结果浏览器访问 404,其实就是没搞清这个目录的访问规则。放 webapp 下可以直接访问,放 WEB-INF 下只能通过 Servlet 转发访问。
3. 编写第一个 Servlet:注解映射与 web.xml 映射
3.1 注解方式 @WebServlet
IDEA 2025 新建 Servlet 非常简单:在 src/main/java 下右键 → New → Servlet,弹出创建向导。填写类名 HelloServlet,然后确认或修改 URL Pattern 为 /hello,点击 OK 即可。
IDEA 会自动生成完整的 Servlet 骨架代码:
java复制package com.example.demo;
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 = "HelloServlet", value = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("<h1>Hello Servlet!</h1>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
这里的 @WebServlet 注解起到了声明映射的作用,value = "/hello" 表示访问路径是 http://localhost:8080/项目名/hello。注意 project name 就是 IDEA 部署配置中 Application context 的值,这个变量很关键,后面配置部署时会详细展开。
3.2 web.xml 方式配置 Servlet
虽然注解方式简洁,但老项目中还是经常看到 web.xml 配置。看懂 web.xml 的 <servlet> 和 <servlet-mapping> 两对标签组合逻辑,对理解 Servlet 映射机制非常有帮助。
xml复制<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.example.demo.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
<servlet> 标签负责"告诉容器我有这个类",<servlet-mapping> 负责"告诉容器这个类对应的访问路径"。两个标签通过 <servlet-name> 建立关联,这个名字可以随意取,但必须一致。URL Pattern 的写法也有讲究:
- 精确匹配:
/hello,只有这个路径能触发。 - 目录匹配:
/api/*,/api/xxx、/api/yyy都能触发。 - 扩展名匹配:
*.do、*.action,Spring MVC 早期版本常用这种。 - 默认映射:
/,匹配所有未匹配到的请求。
如果同时有注解和 web.xml 映射了两个相同的 URL Pattern,规范里说容器应当以 web.xml 为准,但实际不同的 Tomcat 版本处理可能不一致。生产项目里尽量不要同一份代码同时用两种方式映射同一个 Servlet,避免行为不可预期。
3.3 两种方式的优缺点对比
| 维度 | 注解方式 | web.xml 方式 |
|---|---|---|
| 配置位置 | 代码内 | 独立配置文件 |
| 易读性 | 高,类名旁边直接看到路径 | 需要打开 xml 文件对照 |
| 解耦性 | 差,路径硬编码在代码里 | 好,修改路径不用改 Java 代码 |
| 适合场景 | 小型项目、快速开发 | 大型项目、多人协作、配置集中管理 |
在 Servlet 学习阶段,我建议两种都写一遍,理解各自的原理和适用场景。实际开发中,注解方式已经成了主流,web.xml 在 Spring Boot 项目中几乎消失了,但阅读老项目代码时仍然离不开它。
4. 将 Tomcat 接入 IDEA 2025 并完成部署配置
4.1 添加 Tomcat Server 运行配置
Servlet 项目不能像普通 Java 类那样直接右键运行,必须把项目部署到 Tomcat 容器里。IDEA 2025 中配置方式如下:
- 点击右上角运行配置下拉框,选择
Edit Configurations。 - 点击左上角
+,在列表中找到Tomcat Server→Local。 - 在
Application server区域选择之前配置好的 Tomcat 路径,IDEA 会自动识别版本号。 - 切换到
Deployment选项卡,点击+,选择Artifact,然后选择项目的war exploded包。 - 在
Application context填入/demo(这个位置可以自定义,就是项目的访问根路径)。 - 点击 OK 保存配置。
这里特别说明一下 war exploded 和 war 的区别。war exploded 意思是将项目以解压目录的形式部署,每次修改代码或资源文件,IDEA 会直接增量更新到 Tomcat 的解压目录中,配合热部署可以实现修改后直接刷新浏览器看到效果,开发效率很高。而 war 是完整的打包文件,每次修改都要重新打包,适合生产环境。开发阶段一定选 war exploded。
4.2 Application context 与 URL 路径的关系
前面提到 Application context 设置为 /demo,那么访问 Servlet 的完整 URL 就是:
code复制http://localhost:8080/demo/hello
8080 是 Tomcat 默认端口,可以在 conf/server.xml 中修改。/demo 是应用上下文路径,/hello 是 Servlet 映射路径。三层路径关系要理清,否则页面 404 时你根本不知道是端口问题、上下文问题还是 Servlet 映射问题。
如果你希望 URL 不带项目名,即直接 http://localhost:8080/hello,可以把 Application context 设置为 /。但这样容易和 Tomcat 自带的 ROOT 应用冲突,不建议在一开始就这么干。
4.3 启动 Tomcat 与访问验证
配置完成后,点击绿色运行按钮启动 Tomcat。观察控制台日志,看到类似以下输出说明启动成功:
code复制Connected to server
[http-nio-8080-exec-1] INFO org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive
然后打开浏览器,访问 http://localhost:8080/demo/hello,能看到页面显示 Hello Servlet! 就算彻底跑通了。
如果启动过程中报端口被占用,最常见的解决方法是修改 Tomcat 端口。在 conf/server.xml 中找到 <Connector port="8080" 改成其他端口,比如 8081。但要注意,这里改的是 HTTP 连接器的端口,不是 SHUTDOWN 端口,别改错了位置。
5. 配置过程中的常见报错与排查链路
5.1 报错一:404 Not Found
404 是最常见的错误,也最容易让人摸不着头脑。它本质上是"请求路径找不到对应的资源",但底层原因可能有三种,排查时按顺序来:
原因 A:项目没成功部署。 打开 IDEA 底部 Services 面板,展开 Tomcat 节点,看部署的 Artifact 是否已经出现。如果 Deployment 列表里是空的,说明配置没生效,回到运行配置的 Deployment 选项卡重新添加 Artifact。
原因 B:URL 路径拼写错误。 检查访问路径是 /demo/hello 还是 /demo/hello/。Servlet 精确匹配模式下,/hello 和 /hello/ 是两个不同的路径,Tomcat 默认不会自动补斜杠。
原因 C:Servlet 类没有被加载。 查看 Tomcat 启动日志,有没有 Servlet [HelloServlet] 相关的初始化信息。如果日志里压根没提到这个类,可能是注解扫描没有覆盖到对应的包,或者 web.xml 中的 <servlet-class> 写错了全限定名。
5.2 报错二:java.lang.ClassNotFoundException: jakarta.servlet.http.HttpServlet
这个报错非常典型,几乎每个新手都会遇到。原因只有一个:Tomcat 运行时没有提供 Servlet API 的 jar 包,但编译器需要它。
在 IDEA 2025 中,编译器使用的依赖是项目配置的,而 Tomcat 运行时的依赖是 Tomcat 安装目录下 lib 文件夹里的 jar 包。如果编译时找不到 Servlet API,说明项目没有关联 Tomcat 的库。解决方法是:
- 右键项目 →
Open Module Settings(或按 F4 快捷键)。 - 进入
Libraries选项卡,点击+→Java,选择 Tomcat 安装目录下的lib/servlet-api.jar(Tomcat 10 对应的是lib/jakarta.servlet-api-5.0.0.jar)。 - 点击 OK 保存。
或者更简单的方法:在 Project Structure → Modules → Dependencies 选项卡中,点击 + → Application Server Library,选择 Tomcat,IDEA 会自动把 Tomcat lib 目录下的所有 jar 包加入依赖。
还有一个变通的方案:在 Maven 或直接下载 Servlet API 的 jar 包放到项目的 WEB-INF/lib 目录下。但我不推荐这么做,因为如果 Tomcat 的 lib 目录里已经有相同类,再放到 WEB-INF/lib 可能出现版本冲突,轻则报 NoSuchMethodError,重则启动报错。
5.3 报错三:java.net.BindException: Address already in use
这个错误一般出现两次端口占用的情况,比如 Eclipse 和 IDEA 同时启动了一个 Tomcat,或者上一次 IDEA 启动的 Tomcat 没有完全关闭。
排查思路:打开命令行,执行 netstat -ano | findstr 8080(Windows)或 lsof -i :8080(macOS/Linux),找到对应端口的进程 PID,然后杀掉进程。如果不想每次手动处理,建议直接改端口:
code复制conf/server.xml
找到 <Connector port="8080" protocol="HTTP/1.1",改成不常用的端口,比如 8899。同时,运行配置里的 HTTP port 也要同步修改,否则 IDEA 检查不到 Tomcat 的启动状态,会一直提示连接失败。
5.4 报错四:Tomcat 启动成功但页面白屏
页面能启动但白屏,一般不是 Tomcat 的问题,而是 index.jsp 或静态资源路径有问题。确认是不是访问了 /demo/,这时默认会跳转到 index.jsp。如果页面白屏,多半是 JSP 编译失败。查看 Tomcat 的 localhost 日志,路径通常在 Tomcat 安装目录 logs/localhost.yyyy-MM-dd.log,里面会有具体的异常堆栈信息。
常见的 JSP 编译错误包括:JSP 里用了老旧的 <%@ page import="javax.servlet.*" %>,而 Tomcat 10 中包名已经变成 jakarta.servlet.*。这种问题定位非常隐蔽,因为 IDEA 的编译不会扫描到 JSP 文件,你只能通过运行时的异常堆栈才能看到。
5.5 报错五:Artifact 未部署 / 运行配置里没有 Tomcat 选项
如果你在 Edit Configurations 里的 + 列表里找不到 Tomcat Server,通常说明 IDEA 没有识别到你的 Tomcat,或者当前项目不是 Web 项目。
解决方式:先到 Settings → Build, Execution, Deployment → Application Servers 中点击 + 手动添加 Tomcat,选择 Tomcat 安装目录。添加成功后回到运行配置,Tomcat Server 选项就会出现。如果还是没有,说明项目类型有问题,请确认新建项目时选择的是 Jakarta EE 或至少导入了 Web 功能。
6. 让 Servlet 开发效率翻倍的 IDEA 2025 设置
6.1 开启自动导包
IDEA 2025 默认关闭自动导包,每次手动 import 非常影响节奏。开启方法:Settings → Editor → General → Auto Import,勾选 Add unambiguous imports on the fly 和 Optimize imports on the fly。前者会在你输入类名后自动补全 import 语句,后者会在你修改代码后自动清理未使用的 import。写 Servlet 代码时,HttpServletRequest、HttpServletResponse 这些类名经常要用,自动导包能节省大量时间。
6.2 配置热部署
IDEA 2025 中,默认每次修改代码后都需要重启 Tomcat 才能生效,这在调试 Servlet 时非常痛苦。开启热部署的方法:
- 打开运行配置,找到
Server选项卡。 - 在
On frame deactivation选项中,选择Update classes and resources。 - 在
On 'Update' action选项中选择Update classes and resources。 - 点击 OK 保存。
这样设置后,切换出 IDEA 窗口或者按 Ctrl+F10,IDEA 会自动增量更新编译后的 class 文件和静态资源到 Tomcat 部署目录,不需要重启容器。需要注意的是,热部署对于 Servlet 类的方法体修改是有效的,但如果修改了类的方法签名或新增了字段,还是需要完全重启才能生效。
6.3 配置 Servlet 代码模板
IDEA 2025 允许自定义代码模板。如果你不想每次新建 Servlet 都手动删除多余的注释或补充关键代码,可以这样做:
Settings→Editor→File and Code Templates→Code选项卡。- 找到
Servlet Class.java,修改模板内容。 - 在模板中预置好
doGet、doPost方法的雏形,并设置好response.setContentType("text/html;charset=UTF-8")。
模板示例如下:
java复制#parse("File Header.java")
package ${PACKAGE_NAME};
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}", value = "/${CLASS_NAME}")
public class ${CLASS_NAME} extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("Hello from ${CLASS_NAME}");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
设置后新建 Servlet 类,IDEA 直接生成可直接访问的代码,省去每次手动修改。
6.4 使用 HTTP Client 测试接口
写完 Servlet 后,用浏览器访问虽然简单,但提交 POST 请求、携带 JSON 数据时就不够方便了。IDEA 2025 自带了 HTTP Client 工具,可以在项目里新建 .http 文件,快速测试接口:
http复制### GET 请求测试
GET http://localhost:8080/demo/hello
### POST 请求测试
POST http://localhost:8080/demo/hello
Content-Type: application/json
{
"name": "servlet"
}
这样比切换浏览器和 Postman 方便得多,特别是在本地调试时,所有请求都能在 IDEA 内完成,而且可以直接查看响应头和响应体。
7. 一个完整的 Servlet 请求生命周期示例
配好了环境,写一个能体现 Servlet 特性的小示例:接收前端参数,动态生成响应并跳转页面。这个示例可以帮助理解 Servlet 的工作原理。
先写一个 LoginServlet:
java复制package com.example.demo;
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 = "LoginServlet", value = "/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("""
<!DOCTYPE html>
<html>
<head><title>登录页面</title></head>
<body>
<h2>请输入用户名和密码</h2>
<form action="/demo/login" method="post">
用户名: <input type="text" name="username"><br><br>
密码: <input type="password" name="password"><br><br>
<input type="submit" value="登录">
</form>
</body>
</html>
""");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
response.setContentType("text/html;charset=UTF-8");
if ("admin".equals(username) && "123456".equals(password)) {
response.getWriter().write("<h2>登录成功,欢迎 " + username + "!</h2>");
} else {
response.getWriter().write("<h2>用户名或密码错误,请<a href='/demo/login'>重试</a></h2>");
}
}
}
启动 Tomcat 后,访问 http://localhost:8080/demo/login,这就是一个完整的 Servlet 处理 GET 请求和 POST 请求的例子。整个过程可以拆解为:
浏览器发送 HTTP 请求 → Tomcat 接收到请求后根据 URL 路径匹配到 LoginServlet → 容器调用对应的 doGet 或 doPost 方法 → Servlet 通过 request 对象读参数、通过 response 对象写响应 → Tomcat 把响应内容发送回浏览器。理解这条链路,后面学习过滤器、监听器和 Spring MVC 就顺理成章了。
8. 从 Servlet 到框架:下一步该学什么
Servlet 配好、跑通之后,不要停留在"会写 hello world"的舒适区。Servlet 是 Java Web 的基石,但真实项目很少直接裸写 Servlet。我的建议是往下走这几步:
-
JSP + Servlet + JDBC:完成一个简单的增删改查案例,理解传统 Java Web 开发的完整流程。这一步能让你体会到 Servlet 在数据交互中的核心作用。
-
Filter 和 Listener:在 Servlet 基础上加一层
@WebFilter实现登录拦截和统一编码,加一层@WebListener监听应用启动事件。这两个组件在实际项目中必不可少。 -
Maven 管理依赖:当你的项目开始引入第三方库时,Maven 的依赖管理优势就体现出来了。这时候再把 IDEA 2025 的 Maven 配置学一遍,包括本地仓库、镜像源、依赖导入等操作。
-
Spring MVC:学完 Servlet 之后再看 Spring MVC,你会瞬间理解
DispatcherServlet为什么是核心控制器,@RequestMapping为什么能替代web.xml里的映射配置。因为有 Servlet 的基础,Spring MVC 的学习曲线会平缓很多。 -
Spring Boot:这是目前 Java Web 开发的主流框架。Spring Boot 内嵌了 Tomcat,不需要再手工部署 WAR 包到外部容器,本质上是对 Servlet 容器的一次封装。理解了 Servlet,再看 Spring Boot 的自动配置会非常有感觉。
等走到 Spring Boot 之后,再回头看今天配置 Servlet 的整个过程,你会发现这些都是基本功。那些配置细节可能在将来的框架开发中不再直接面对,但排查问题的思路——检查版本匹配、查看运行时日志、分模块隔离变量——会一直复用下去。
