Servlet(Server Applet)是 Java EE 规范的一部分,它是一种用于开发动态 Web 资源的技术,Servlet 就是一个运行在 Web 服务器端的 Java 小程序,它接收来自客户端(通常是浏览器)的请求,并返回响应。

核心概念:Servlet 接口
javax.servlet.Servlet 接口是所有 Servlet 必须实现的顶级接口,它定义了 Servlet 与 Servlet 容器(如 Tomcat、Jetty)之间进行生命周期交互的契约。
一个典型的 Servlet 开发流程是:
- 创建一个 Java 类。
- 让这个类实现
Servlet接口,并实现其所有方法。 - 在
web.xml文件中配置该 Servlet,将一个 URL 路径映射到这个 Java 类。 - 将应用打包成 WAR 文件,部署到 Servlet 容器中。
Servlet 接口的生命周期方法
Servlet 接口定义了三个核心的生命周期方法,以及两个其他方法,Servlet 容器(如 Tomcat)负责调用这些方法。
init(ServletConfig config)
- 调用时机:当 Servlet 容器首次加载该 Servlet 实例时,会调用此方法。一个 Servlet 在其生命周期中只会被初始化一次。
- 作用:完成一次性的初始化操作,加载配置文件、建立数据库连接、创建缓存等。
- 参数:
ServletConfig对象,包含了 Servlet 的配置信息(如初始化参数)。 - 示例:
@Override public void init(ServletConfig config) throws ServletException { // 获取初始化参数 String driver = config.getInitParameter("dbDriver"); System.out.println("Servlet 正在初始化,数据库驱动: " + driver); // ... 其他初始化代码 ... }
service(ServletRequest request, ServletResponse response)
- 调用时机:每当客户端(浏览器)向该 Servlet 发送请求时,容器就会调用此方法。每次请求都会调用一次。
- 作用:这是 Servlet 的核心方法,用于处理客户端请求并生成响应,它会根据请求的类型(GET, POST, PUT, DELETE 等)来调用相应的
doGet(),doPost()等方法。 - 注意:通常我们不会直接重写
service()方法,而是重写doGet(),doPost()等。GenericServlet(一个抽象类)已经为我们实现了service()方法,它会根据请求的 HTTP 方法来分发到具体的doXxx()方法。 - 示例:
// 在 GenericServlet 或 HttpServlet 中,我们通常不直接重写这个 // 而是重写 doGet 或 doPost
destroy()
- 调用时机:当 Servlet 容器决定卸载该 Servlet 实例时(服务器关闭或应用被移除),会调用此方法。一个 Servlet 在其生命周期中也只会被销毁一次。
- 作用:进行资源清理,关闭数据库连接、释放文件句柄等。
- 示例:
@Override public void destroy() { System.out.println("Servlet 正在销毁,正在关闭数据库连接..."); // ... 清理资源的代码 ... }
Servlet 接口的其它方法
ServletConfig getServletConfig()
- 作用:返回
ServletConfig对象,该对象在init()方法中被传入,通过这个对象,可以获取 Servlet 的初始化参数、Servlet 上下文等。 - 示例:
@Override public ServletConfig getServletConfig() { return this.servletConfig; }
String getServletInfo()
- 作用:返回一个包含 Servlet 信息的字符串,如作者、版本、版权等,这只是一个辅助信息,容器可能会用它来管理 Servlet。
- 示例:
@Override public String getServletInfo() { return "My First Servlet, Version 1.0"; }
实际开发:使用 HttpServlet
直接实现 Servlet 接口非常繁琐,因为需要处理很多底层细节,在实际开发中,我们几乎总是继承 javax.servlet.http.HttpServlet 抽象类。

HttpServlet 已经帮我们实现了:
Servlet接口的所有方法。service()方法,它会根据 HTTP 请求方法(GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE)来调用对应的doGet(),doPost()等方法。
我们只需要:
- 创建一个类,继承
HttpServlet。 - 重写
doGet()或doPost()等方法,来处理具体的业务逻辑。 - 配置
web.xml或使用注解。
示例代码
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;
// 使用注解进行配置,替代 web.xml
// @WebServlet("/hello") // 将此 Servlet 映射到 /hello 路径
public class HelloServlet extends HttpServlet {
// 初始化方法(可选)
@Override
public void init() throws ServletException {
System.out.println("HelloServlet 初始化...");
}
// 处理 GET 请求
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 设置响应内容类型和字符编码
resp.setContentType("text/html;charset=UTF-8");
// 2. 获取输出流,用于向客户端写入响应内容
PrintWriter out = resp.getWriter();
// 3. 生成 HTML 响应
out.println("<html>");
out.println("<head><title>Hello Servlet</title></head>");
out.println("<body>");
out.println("<h1>你好,世界!</h1>");
out.println("<p>这是我的第一个 Servlet 程序。</p>");
out.println("</body>");
out.println("</html>");
}
// 处理 POST 请求
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// GET 和 POST 的处理逻辑可能不同
// POST 用于提交表单数据
String username = req.getParameter("username");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.println("<html><body>");
out.println("<h1>POST 请求成功!</h1>");
out.println("欢迎你, " + (username != null ? username : "访客"));
out.println("</body></html>");
}
// 销毁方法(可选)
@Override
public void destroy() {
System.out.println("HelloServlet 销毁...");
}
}
配置方式
有两种主要的配置方式:
传统方式:web.xml (在 src/main/webapp/WEB-INF/web.xml 中)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- Servlet 注册和映射 -->
<servlet>
<!-- Servlet 的内部名称,可以自定义 -->
<servlet-name>HelloServlet</servlet-name>
<!-- Servlet 的全限定类名 -->
<servlet-class>com.example.HelloServlet</servlet-class>
<!-- 初始化参数(可选) -->
<init-param>
<param-name>dbDriver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
</servlet>
<servlet-mapping>
<!-- 将哪个 Servlet 映射到哪个 URL -->
<servlet-name>HelloServlet</servlet-name>
<!-- URL 模式,/hello 表示访问路径 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
现代方式:使用注解 @WebServlet (推荐)
从 Servlet 3.0 开始,支持使用注解来简化配置,如上面示例代码中的 @WebServlet("/hello")。

- 优点:配置简单,代码和配置在一起,无需维护
web.xml。 @WebServlet常用属性:value或urlPatterns:指定 URL 模式。@WebServlet(value = "/hello")或@WebServlet(urlPatterns = {"/hello", "/hi"})。
HttpServletRequest 和 HttpServletResponse
在 doGet 和 doPost 方法中,我们最常操作的就是这两个对象:
-
HttpServletRequest:代表客户端的请求对象,它封装了所有的请求信息。req.getMethod(): 获取 HTTP 方法 (GET, POST)。req.getRequestURI(): 获取请求的 URI。req.getParameter("name"): 获取请求参数的值(用于表单提交)。req.getHeader("User-Agent"): 获取请求头信息。req.getSession(): 获取或创建HttpSession对象,用于会话管理。
-
HttpServletResponse:代表服务器的响应对象,我们通过它来向客户端返回数据。resp.setContentType("text/html;charset=UTF-8"): 设置响应内容的类型和字符编码,防止中文乱码。resp.setStatus(200): 设置 HTTP 状态码(200 表示成功,404 表示未找到等)。resp.setHeader("Cache-Control", "no-cache"): 设置响应头。resp.getWriter(): 获取字符输出流,用于输出文本内容。resp.getOutputStream(): 获取字节输出流,用于输出图片、文件等二进制内容。
| 概念 | 描述 |
|---|---|
Servlet 接口 |
所有 Servlet 的顶层接口,定义了生命周期契约。 |
| 生命周期 | init() -> service() (多次) -> destroy()。 |
HttpServlet |
实际开发中使用的基类,简化了 HTTP 请求处理。 |
doGet/doPost |
我们最常重写的方法,用于处理具体的业务逻辑。 |
HttpServletRequest |
封装了客户端的请求信息。 |
HttpServletResponse |
封装了服务器的响应信息。 |
| 配置 | 传统 web.xml 和现代注解 @WebServlet 两种方式。 |
理解 Servlet 接口及其生命周期是掌握 Java Web 开发的基础,虽然现在有很多更高级的框架(如 Spring MVC),但它们在底层依然是基于 Servlet 原理工作的,学好 Servlet 对于理解整个 Java Web 生态系统至关重要。
