0%

Servlet接口

Servlet 接口详解:Java Web 开发的基石

Servlet 是 Java Web 技术的核心组件,负责处理客户端请求并生成动态响应。它由 Servlet 容器管理,遵循标准化的生命周期,是构建 Java Web 应用的基础。本文将从 Servlet 的核心概念、接口方法、生命周期、配置方式及相关对象等方面,全面解析 Servlet 技术。

Servlet 与 Servlet 容器

1. 什么是 Servlet?

Servlet 是运行在 Web 服务器中的 Java 类,用于处理客户端(如浏览器)的 HTTP 请求并生成动态内容。它具有以下特点:

  • 平台无关:基于 Java 技术,可在任何支持 Java 的 Web 服务器上运行;
  • 由容器管理:生命周期(创建、初始化、服务、销毁)完全由 Servlet 容器控制;
  • 动态内容生成:通过接收请求参数、访问数据库等方式,生成个性化响应。

2. 什么是 Servlet 容器?

Servlet 容器是 Web 服务器(如 Tomcat、Jetty)的一部分,负责与 Servlet 交互并管理其生命周期。其核心功能包括:

  • 加载和实例化 Servlet 类;
  • 调用 Servlet 的生命周期方法(initservicedestroy);
  • 处理 HTTP 请求与响应的封装(将底层 TCP 数据转换为 HttpServletRequest/HttpServletResponse 对象);
  • 管理 Servlet 之间的共享资源(如 ServletContext)。

Servlet 接口核心方法

javax.servlet.Servlet 接口定义了 Servlet 与容器交互的标准协议,包含 5 个核心方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface Servlet {
// 初始化 Servlet,容器创建 Servlet 后调用,仅执行一次
void init(ServletConfig config) throws ServletException;

// 获取 Servlet 的配置信息(如初始化参数)
ServletConfig getServletConfig();

// 处理客户端请求,每次请求都会调用
void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;

// 返回 Servlet 的元信息(如作者、版本)
String getServletInfo();

// 销毁 Servlet,释放资源,容器卸载时调用,仅执行一次
void destroy();
}

方法详解:

  1. init(ServletConfig config)
    • 触发时机:Servlet 实例被创建后(首次请求时或容器启动时,取决于 load-on-startup 配置);
    • 作用:初始化资源(如加载配置、连接数据库),config 参数包含 Servlet 的配置信息;
    • 注意:若重写此方法,需确保调用 super.init(config)(如在 GenericServlet 中),否则 getServletConfig() 会返回 null
  2. service(ServletRequest req, ServletResponse res)
    • 触发时机:每次客户端请求该 Servlet 时;
    • 作用:接收请求(ServletRequest)、处理业务逻辑、生成响应(ServletResponse);
    • 注意:ServletRequestServletResponse 是通用接口,HTTP 场景下会被转换为 HttpServletRequestHttpServletResponse
  3. destroy()
    • 触发时机:Servlet 容器关闭或应用卸载时;
    • 作用:释放资源(如关闭数据库连接、停止后台线程)。

Servlet 的继承体系

为简化开发,Java 提供了 Servlet 接口的实现类,形成以下继承关系:

1. GenericServlet

实现 ServletServletConfig 接口,提供默认实现:

  • 封装 ServletConfig 对象,可直接调用 getInitParameter() 等方法;
  • 提供无参 init() 方法,避免重写 init(ServletConfig) 时忘记保存配置对象;
  • 未实现 service() 方法(仍为抽象方法),需子类实现。

2. HttpServlet

继承 GenericServlet,专为 HTTP 协议设计,重写 service() 方法实现请求分发:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 根据 HTTP 方法(GET/POST 等)分发到对应方法
String method = request.getMethod();
if (method.equals("GET")) {
doGet(request, response);
} else if (method.equals("POST")) {
doPost(request, response);
}
// 其他方法(PUT/DELETE 等)的处理...
}

开发中通常继承 HttpServlet,只需重写 doGet()doPost() 即可处理 HTTP 请求:

1
2
3
4
5
6
7
8
9
10
11
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello, GET!");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello, POST!");
}
}

Servlet 的注册与映射

Servlet 需在配置文件中注册并映射 URL 路径,才能被容器识别和访问。配置方式有两种:XML 配置注解配置(Servlet 3.0+)。

XML 配置(web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- 注册 Servlet -->
<servlet>
<servlet-name>MyServlet</servlet-name> <!-- 唯一标识 -->
<servlet-class>com.example.MyServlet</servlet-class> <!-- 全类名 -->
<!-- 初始化参数(仅当前 Servlet 可见) -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 加载时机:0 或正数表示容器启动时加载,值越小优先级越高;负数表示首次请求时加载 -->
<load-on-startup>1</load-on-startup>
</servlet>

<!-- 映射 URL 路径 -->
<servlet-mapping>
<servlet-name>MyServlet</servlet-name> <!-- 与注册时的名称一致 -->
<url-pattern>/myServlet</url-pattern> <!-- 访问路径,以 / 开头 -->
</servlet-mapping>

注解配置(Servlet 3.0+)

无需 web.xml,直接在 Servlet 类上添加 @WebServlet 注解:

1
2
3
4
5
6
7
8
9
@WebServlet(
name = "MyServlet",
urlPatterns = "/myServlet",
initParams = {@WebInitParam(name = "encoding", value = "UTF-8")},
loadOnStartup = 1
)
public class MyServlet extends HttpServlet {
// ...
}

缺省 Servlet

容器(如 Tomcat)内置一个 “缺省 Servlet”,用于处理未被其他 Servlet 映射的请求(如静态资源:HTML、CSS 等)。其配置如下:

1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern> <!-- 匹配所有未被映射的请求 -->
</servlet-mapping>

Servlet 相关核心对象

ServletConfig

每个 Servlet 实例对应一个 ServletConfig 对象,用于获取当前 Servlet 的初始化参数和 ServletContext

1
2
3
4
5
6
// 获取初始化参数
String encoding = getServletConfig().getInitParameter("encoding"); // 对应 <init-param>
Enumeration<String> paramNames = getServletConfig().getInitParameterNames();

// 获取 ServletContext
ServletContext context = getServletConfig().getServletContext();

ServletContext

代表整个 Web 应用,全局唯一,所有 Servlet 共享。主要功能:

  • 获取全局初始化参数(web.xml<context-param> 配置);
  • 访问 Web 应用资源(如获取文件路径、读取资源流);
  • 共享数据(通过 setAttribute/getAttribute)。

示例

1
2
3
4
5
<!-- 全局初始化参数(所有 Servlet 可见) -->
<context-param>
<param-name>appName</param-name>
<param-value>MyWebApp</param-value>
</context-param>
1
2
3
4
5
6
7
8
9
10
// 在 Servlet 中获取
ServletContext context = getServletContext();
String appName = context.getInitParameter("appName"); // "MyWebApp"

// 获取资源路径(服务器上的绝对路径)
String realPath = context.getRealPath("/WEB-INF/config.xml");

// 共享数据
context.setAttribute("userCount", 100);
int count = (int) context.getAttribute("userCount");

Servlet 生命周期

Servlet 的生命周期完全由容器管理,分为 4 个阶段:

1. 实例化(构造器)

  • 触发时机:容器首次加载 Servlet 时(根据 load-on-startup 配置);
  • 操作:容器调用 Servlet 的无参构造器创建实例(仅一次)。

2. 初始化(init()

  • 触发时机:实例创建后立即调用;
  • 操作:执行初始化逻辑(如加载配置、连接数据库),由 init(ServletConfig) 实现,开发者可重写无参 init()

3. 服务(service()

  • 触发时机:每次客户端请求该 Servlet 时;
  • 操作:容器创建新线程调用 service() 方法,处理请求并生成响应。对于 HTTP 请求,HttpServlet 会分发到 doGet()/doPost() 等方法。

4. 销毁(destroy()

  • 触发时机:容器关闭或应用卸载时;
  • 操作:执行资源清理逻辑(如关闭连接、释放内存),仅调用一次。

生命周期流程图

1
容器启动/首次请求 → 构造器(实例化) → init()(初始化) → 每次请求调用 service() → 容器关闭 → destroy()(销毁)

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10