Servlet概述:体系结构,生命周期,常用命令,注解配置

相关链接:

一、Servlet简介

Servlet(Server Applet),全称Java Servlet。是用Java编写的服务器端程序,其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

Servlet工作模式

  1. 客户端发送请求至服务器;
  2. 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器;
  3. 服务器将响应返回客户端。

二、Servlet的体系结构

Servlet由两个Java包组成:javax.servlet和javax.servlet.http。在javax.servlet包中定义了所有的Servlet类都必须实现或扩展的的通用接口和类;在javax.servlet.http包中定义了采用HTTP通信协议的HttpServlet类。其中的一些比较核心的接口和类之间的关系如下,图中提到的方法是在使用该接口或类时必须要实现的:

实现
实现
实现
继承
实现
«Servlet的根接口»
Servlet
+service(req, res)
+init(config)
+destroy()
«Servlet的配置接口»
ServletConfig
«Servlet的序列化接口»
Serializable
«通用的Servlet抽象类,与协议无关»
GenericServlet
+service(req, res)
+init(config)
+destroy()
«Http协议的Serclet抽象类»
HttpServlet

1. Servlet 接口

Servlet 接口是所有 Servlet 类的根接口。其常用方法如下:

// 初始化 Servlet
public void init(ServletConfig config) throws ServletException;
// 获取 Servlet 的配置信息
public ServletConfig getServletConfig();
// 处理请求
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
// 获取 Servlet 的信息
public String getServletInfo();
// 销毁 Servlet
public void destroy();

2. Serializable 接口

Serializable 接口是 Java 中的标记接口,用于标识类的实例可以被序列化。实现该接口的类表示它们的实例可以被转换为字节序列,以便在网络上传输或保存到文件中。其常用方法如下:

// 序列化对象
private void writeObject(ObjectOutputStream out) throws IOException;
// 反序列化对象
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

3. ServletConfig 接口

ServletConfig 接口提供了 Servlet 配置信息的访问方法。具体来说,它允许 Servlet 访问在部署描述符中配置的初始化参数,以及获取与 ServletContext 相关联的配置信息。其常用方法如下:

// 获取 Servlet 的名称
public String getServletName();
// 获取初始化参数
public String getInitParameter(String name);
// 获取所有初始化参数的名称
public Enumeration<String> getInitParameterNames();
// 获取 ServletContext
public ServletContext getServletContext();

4. GenericServlet 抽象类

GenericServlet 实现了 Servlet 接口,为 Servlet 提供了一些通用的功能,但它本身并不直接处理 HTTP 请求和响应。GenericServletservice() 方法接受通用的 ServletRequestServletResponse 对象。其常用方法如下:

// 初始化 Servlet
public void init(ServletConfig config) throws ServletException;
// 获取 Servlet 的配置信息
public ServletConfig getServletConfig();
// 获取 Servlet 的名称
public String getServletName();
// 处理请求
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
// 销毁 Servlet
public void destroy();
// 获取初始化参数
public String getInitParameter(String name);
// 获取所有初始化参数的名称
public Enumeration<String> getInitParameterNames();

5. HttpServlet 抽象类

HttpServlet 继承自 GenericServlet,专门用于处理 HTTP 请求和响应。HttpServlet 提供了对 HTTP 请求方法的更直接的支持,如 doGet()doPost() 等。其常用方法如下:

// 处理 HTTP GET 请求
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
// 处理 HTTP POST 请求
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
// 处理 HTTP PUT 请求
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
// 处理 HTTP DELETE 请求
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
// 处理 HTTP HEAD 请求
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
// 处理 HTTP OPTIONS 请求
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
// 处理 HTTP TRACE 请求
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
// 处理 HTTP PATCH 请求
protected void doPatch(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
// 处理通用的 HTTP 请求
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;

三、Servlet的生命周期

Servlet 的生命周期指一个Servlet 对象从创建到销毁的过程,其生命周期分为四个阶段:实例化初始化处理请求服务终止init()service()destroy()是 Servlet 生命周期的方法,分别对应 Servlet 生命周期的后三个阶段,方法中的代码在处于对应的生命周期时被执行。

1. 实例化阶段

当用户第一次向 Servlet 容器发出 HTTP 请求要求访问某个 Servlet 时,Servlet 容器会在整个容器中搜索该 Servlet 对象,如果发现这个 Servlet 对象没有被实例化,便创建这个 Servlet 对象,之后进入初始化阶段;如果找到了该 Servlet 对象的实例,则不去创建而是直接进入运行阶段。

2. 初始化阶段

在创建 Servlet 对象后会调用该对象的 init() 方法完成初始化,随后 Servlet 进入到运行阶段。

注意:在 Servlet 对象的整个生命周期内,它的 init() 方法只会在创建该对象时被调用一次。

3. 运行阶段

这是 Servlet 生命周期中最核心的阶段。在该阶段中,Servlet 容器会为当前的请求创建一个 ServletRequest 对象和一个 ServletResponse 对象(分别代表请求和响应),service() 方法从 ServletRequest 对象中获得用户的详细请求信息并可以检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法处理该请求,处理完成后通过 ServletResponse 对象生成响应结果。

注意:在 Servlet 对象的整个生命周期内,用户每次请求访问 Servlet 时,Servlet 容器都会调用一次 Servlet 的 service() 方法,并且创建新的 ServletRequest 和 ServletResponse 对象。

4. 销毁阶段

当服务器停止时,Servlet 容器需要回收 Servlet 对象所占用的内存,在回收之前,会自动调用该对象的 destroy() 方法做好回收内存前的准备,辟如关闭后台线程。

注意:在 Servlet 对象的整个生命周期内,destroy() 方法只会在销毁该对象被调用一次。Servlet 对象一旦创建就会驻留在内存中一直等待客户端的访问,直到服务器关闭或项目被移除出容器时,Servlet 对象才会被销毁。

四、Servlet的注解配置

1. xml配置

假设一个java EE项目中存在com.example.SimpleServlet.java这个类,其中的代码如下:

package com.example.SimpleServlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SimpleServlet extends HttpServlet {
    // 处理get请求
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        PrintWriter out = resp.getWriter(); // 实例化out对象。
        out.println("<HTML>");
        out.println("<HEAD>");
        out.println("<TITLE>THE FIRST SERVLET</TITLE>");
        out.println("</HEAD>");
        out.println("<BODY>");
        out.println("<H1>Hello World!</H1>");
        out.println("</BODY>");
        out.println("</HTML>");
        out.close();
    }

    // 处理post请求
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        this.doGet(req, resp);
    }
}

那么如果我们想要通过浏览器对这个 Servlet 类发送请求并进行响应,就要先在项目的xml文件中配置地址映射:

<servlet>
       <servlet-name>simple</servlet-name>
       <servlet-class>com.example.SimpleServlet</servlet-class>
</servlet>

<servlet-mapping>
       <servlet-name>simple</servlet-name>
       <url-pattern>/demo</url-pattern> 
</servlet-mapping>

配置好映射后启动项目,我们便可以通过输入网址http://localhost:8080/demo来访问这个Servlet应用。

上面的xml文件中的标签及对应含义如下:

  • <servlet-name>:定义的Servlet应用名字;
  • <servlet-class>:定义的Servlet应用名字所对应的具体Servlet文件;
  • <servlet-mapping>:地址映射
  • <servlet-name>:定义的Servlet应用名字;
  • <url-pattern>:映射的地址。

2. 注解配置

Servlet 的注解配置是一种简化 Servlet 配置的方式,通过在 Servlet 类上使用注解,可以替代传统的在 web.xml 文件中配置 Servlet 的方式。注解配置使得 Servlet 的定义更加直观和简洁,减少了配置的繁琐性。Servlet3.0提供了注解(annotation),我们可以不用在web.xml里面配置servlet,只需要加上@WebServlet注解就可以修改该servlet的属性。

以下是 Servlet 常用注解及其说明:

注解说明示例配置值
@WebServlet标识一个类为 Servlet,并指定访问路径等配置@WebServlet(urlPatterns = "/example", name = "ExampleServlet")urlPatterns, name, loadOnStartup, asyncSupported
@WebInitParam@WebServlet 中设置初始化参数@WebServlet(initParams = {@WebInitParam(name = "paramName", value = "paramValue")})name, value
@HttpMethodConstraint指定对特定 HTTP 方法的约束条件@HttpMethodConstraint(value = "GET", rolesAllowed = "admin")value, emptyRoleSemantic, transportGuarantee
@ServletSecurity配置 Servlet 的安全约束@ServletSecurity(@HttpConstraint(transportGuarantee = ServletSecurity.TransportGuarantee.CONFIDENTIAL, rolesAllowed = "user"))@HttpConstraint 中的各个属性
@MultipartConfig配置 Servlet 处理文件上传的相关参数@MultipartConfig(location = "/tmp", fileSizeThreshold = 1024 * 1024, maxFileSize = 1024 * 1024 * 5, maxRequestSize = 1024 * 1024 * 5 * 5)location, fileSizeThreshold, maxFileSize, maxRequestSize
@WebFilter标识一个类为过滤器,并指定过滤路径@WebFilter(filterName = "MyFilter", urlPatterns = "/*")filterName, urlPatterns, dispatcherTypes, initParams
@WebListener标识一个类为监听器@WebListener

使用注解配置,我们可以将上面的xml配置简化为@WebServlet(name = "simple", urlPatterns = "/demo"),通过在对应的 Servlet 类上使用该注解可以更方便地实现实现地址映射。

五、Http协议请求的处理与响应

ServletRequestServletResponse 接口是Servlet中定义的两个核心接口,用于处理与客户端的通信。

  • ServletRequest 提供了一种通用的方式来获取客户端请求的信息,包括请求参数、请求头、会话等,它是与协议无关的接口,适用于处理各种类型的请求,不仅限于 HTTP。
  • ServletResponse 用于封装服务器对客户端的响应。它提供了设置响应状态码、响应头、写入响应体等方法。与 ServletRequest 类似,ServletResponse 也是与协议无关的接口,可用于处理各种类型的响应。

HttpServletRequestHttpServletResponse 分别是上面两个接口的子接口,专门用于处理 HTTP 请求和响应。它们扩展了 上面两个接口,提供了更丰富的处理 HTTP 请求和响应的方法。

  • HttpServletRequest 提供了获取 HTTP 方法、请求 URI、请求头等特定于 HTTP 的信息。
  • HttpServletResponse 提供了设置 HTTP 状态码、响应头、Cookie 等特定于 HTTP 的功能。
继承
继承
«接口»
ServletRequest
«接口»
ServletResponse
«接口»
HttpServletRequest
«接口»
HttpServletResponse

1. HttpServletRequest常用方法

// 获取请求的方法(如 GET、POST)
public String getMethod();
// 获取请求的 URI
public String getRequestURI();
// 获取请求头的值
public String getHeader(String name);
// 获取所有请求头的名称
public Enumeration<String> getHeaderNames();
// 获取请求参数的值
public String getParameter(String name);
// 获取所有请求参数的名称
public Enumeration<String> getParameterNames();
// 获取请求参数的所有值
public String[] getParameterValues(String name);
// 获取 Cookie 数组
public Cookie[] getCookies();
// 获取会话(如果不存在则创建)
public HttpSession getSession();
// 获取会话(如果不存在则创建),指定是否创建新的会话
public HttpSession getSession(boolean create);
// 获取请求的字符编码
public String getCharacterEncoding();
// 获取请求的内容长度
public int getContentLength();
// 获取请求的内容类型
public String getContentType();
// 设置响应状态码
public void setStatus(int sc);
// 设置响应头
public void setHeader(String name, String value);
// 添加响应头
public void addHeader(String name, String value);
// 设置响应内容的字符编码
public void setCharacterEncoding(String charset);
// 设置响应内容的类型
public void setContentType(String type);
// 获取响应的字符输出流
public PrintWriter getWriter() throws IOException;
// 获取响应的字节输出流
public ServletOutputStream getOutputStream() throws IOException;
// 设置响应的缓存控制
public void setCacheControl(String control);
// 设置响应的过期时间
public void setDateHeader(String name, long date);
// 设置响应的内容长度
public void setContentLength(int len);
// 发送重定向响应
public void sendRedirect(String location) throws IOException;
// 向响应输出文本
public void PrintWriter writer.println(String text) throws IOException;

2. HttpServletResponse常用方法

// 设置响应状态码
public void setStatus(int sc);
// 设置响应头
public void setHeader(String name, String value);
// 添加响应头
public void addHeader(String name, String value);
// 设置响应内容的字符编码
public void setCharacterEncoding(String charset);
// 设置响应内容的类型
public void setContentType(String type);
// 获取响应的字符输出流
public PrintWriter getWriter() throws IOException;
// 获取响应的字节输出流
public ServletOutputStream getOutputStream() throws IOException;
// 设置响应的缓存控制
public void setCacheControl(String control);
// 设置响应的过期时间
public void setDateHeader(String name, long date);
// 设置响应的内容长度
public void setContentLength(int len);
// 发送重定向响应
public void sendRedirect(String location) throws IOException;
// 向响应输出文本
public void PrintWriter writer.println(String text) throws IOException;

六、Servlet的上下文

Servlet上下文又叫做:ServletContext。当WEB服务器启动时,会为每一个WEB应用程序(webapps下的每个目录就是一个应用程序)创建一块共享的存储区域。ServletContext也叫做“公共区域”,也就是同一个WEB应用程序中,所有的Servlet和JSP都可以共享同一个区域。ServletContext在WEB服务器启动时创建,服务器关闭时销毁。容器在启动的时候,会为每一个web应用创建唯一的一个符合ServletContext接口的对象,该对象一般称之为"servlet上下文"。

1. 主要作用

存储初始化参数:

  • Servlet 上下文允许在部署描述符中配置的初始化参数,这些参数对整个应用程序都是可见的。
  • 通过 ServletConfig 的 getInitParameter() 方法或直接在 Servlet 中使用 getServletContext().getInitParameter() 方法访问。

获取资源:

  • Servlet 上下文提供了获取 Web 应用程序中资源的方法,如 HTML 文件、图片、配置文件等。
  • 通过 getServletContext().getResourceAsStream() 方法可以获取资源的输入流。

共享属性:

  • Servlet 上下文允许在不同的 Servlet 之间共享属性。这些属性可以存储在上下文中,并在整个应用程序中访问。
  • 使用 getServletContext().setAttribute() 设置属性,通过 getServletContext().getAttribute() 获取属性。

获得 Web 应用程序信息:

  • 可以获取 Web 应用程序的相关信息,如应用程序名称、服务器信息等。
  • 通过 getServletContext().getServletContextName() 获取应用程序名称。

发送事件通知:

  • Servlet 上下文可以向监听器发送事件通知,用于监听应用程序生命周期事件或属性变化等。
  • 监听器通过实现相应的接口(如 ServletContextListenerServletContextAttributeListener)来处理这些事件。

2. ServletContext常用方法

// 获取 Servlet 上下文的初始化参数值
public String getInitParameter(String name);
// 获取 Servlet 上下文的 MIME 类型映射
public String getMimeType(String file);
// 获取 Servlet 上下文中的真实路径
public String getRealPath(String path);
// 获取 Servlet 上下文的资源流
public InputStream getResourceAsStream(String path);
// 获取 Servlet 上下文的属性值
public Object getAttribute(String name);
// 设置 Servlet 上下文的属性值
public void setAttribute(String name, Object object);
// 移除 Servlet 上下文的属性
public void removeAttribute(String name);
// 获取 Servlet 上下文中的 RequestDispatcher
public RequestDispatcher getRequestDispatcher(String path);
// 获取 Servlet 上下文中的 Servlet
public Servlet getServlet(String name) throws ServletException;
// 添加映射到 Servlet 上下文的过滤器
public FilterRegistration.Dynamic addFilter(String filterName, String className);
// 添加映射到 Servlet 上下文的过滤器
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter);
// 添加映射到 Servlet 上下文的监听器
public void addListener(Class<? extends EventListener> listenerClass);
// 添加映射到 Servlet 上下文的监听器
public <T extends EventListener> void addListener(T t);
// 获取 Servlet 上下文中的会话超时时间
public int getSessionTimeout();
// 获取 Servlet 上下文中的会话 Cookie 配置
public SessionCookieConfig getSessionCookieConfig();
// 添加映射到 Servlet 上下文的 Servlet
public ServletRegistration.Dynamic addServlet(String servletName, String className);
// 添加映射到 Servlet 上下文的 Servlet
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet);
// 获取 Servlet 上下文中的所有 Servlet 注册器
public Map<String, ? extends ServletRegistration> getServletRegistrations();

七、Cookie与Session

1. Cookie

HTTP是一种不保存状态的协议,即无状态(stateless)协议。HTTP协议自身不对请求和响应之间的通信状态进行保存和持久化处理,为了实现对用户状态的持久化管理,HTTP引入了Cookie技术。Cookie是一种在用户浏览器中存储小型文本信息的机制,由服务器通过HTTP协议发送并存储至客户端,以便在后续请求中跟踪用户会话、存储用户偏好设置等。其工作原理如下:

  1. 浏览器端第一次发送请求到服务器端;
  2. 服务器端创建Cookie,该Cookie中包含用户的信息,然后将该Cookie发送到浏览器端;
  3. 浏览器端再次访问服务器端时会携带服务器端创建的Cookie;
  4. 服务器端通过Cookie中携带的数据区分不同的用户。

Cookie是通过HTTP请求和响应头在客户端和服务器端传递的:

  • 在请求头中,采用名为“Cookie”的字段,客户端将存储的Cookie发送给服务器端,格式为“Cookie: a=A; b=B; c=C”。多个Cookie可以共用一个请求头,并用分号隔开,一个请求头中有一个Cookie字段;
  • 在响应头中,采用名为“Set-Cookie”的字段,服务器端把需要存储的Cookie发送给客户端,格式为“Set-Cookie: a=A; b=B; c=C;”。多个Cookie可以共用一个响应头,并用分号隔开,一个响应头中也可以有多个Set-Cookie字段。

在Servlet中,类java.servlet.http.Cookie封装了相关的方法用于创建和操作Cookie。

Cookie常用方法
// 构造方法
Cookie(String name, String value);
// 将 Cookie 添加到响应头
void addCookie(Cookie cookie);
// 设置 Cookie 的存放路径
void setPath(String uri);
// 获取 Cookie 的路径
String getPath();
// 设置 Cookie 的域
void setDomain(String pattern);
// 获取 Cookie 的域
String getDomain();
// 设置 Cookie 的过期时间,以秒为单位
void setMaxAge(int expiry);
// 获取 Cookie 的过期时间
int getMaxAge();
// 获取 Cookie 的名称
String getName();
// 获取 Cookie 的值
String getValue();
Cookie的过期时间

负数:表示Cookie只保存在浏览器的内存中,关闭浏览器Cookie即被删除;
正数:表示Cookie保存在计算机硬盘中的的秒数,到期即从硬盘中删除Cookie;
零:表示删除该Cookie。

示例代码

创建和发送Cookie:

// 创建cookie对象
Cookie cookie = new Cookie("name", "admin");
// 发送cookie
response。addCookie(cookie);

获取Cookie:

// 获取cookies数组
Cookie[] cookies = request.getCookies();
// 判断数组是否为空
if (cookie != null && cookies.length > 0) {
	// 遍历cookies数组
	for (Cookie cookie : cookies) {
		System.out.printIn(cookie.getName());
		System.out.printIn(cookie.getValue());
	}
}

2. Session

Session是在HTTP协议的基础上实现对用户状态的持久化管理的一种机制。Cookie和Session都可以用于跟踪用户的会话,以便识别同一用户的多次请求,但与Cookie不同的是,Session将用户状态信息存储在服务器端,而不是在用户浏览器中。与Cookie相比,Session提供了更高的安全性,但也增加了服务器的存储和管理负担,其工作原理如下:

  1. 用户第一次访问服务器时,服务器会为该用户创建一个唯一的Session标识,通常称为Session ID;
  2. 服务器将该Session ID通过Cookie发送给用户的浏览器,或者将其包含在URL中;
  3. 用户的浏览器在后续的请求中携带这个Session ID;
  4. 服务器根据携带的Session ID来识别用户,并检索与之关联的Session数据,实现对用户状态的保持。

在Servlet中,类javax.servlet.http.HttpSession封装了相关的方法用于创建和操作Session。

HttpSession常用方法
// 获取或创建 Session 对象
HttpSession getSession();
// 获取或创建 Session 对象,并指定是否创建新的 Session
HttpSession getSession(boolean create);
// 将属性设置到 Session 中
void setAttribute(String name, Object value);
// 从 Session 中获取属性值
Object getAttribute(String name);
// 从 Session 中移除属性
void removeAttribute(String name);
// 获取 Session 的唯一标识符
String getId();
// 获取 Session 的创建时间
long getCreationTime();
// 获取 Session 的最后访问时间
long getLastAccessedTime();
// 设置 Session 的最大不活动时间,以秒为单位
void setMaxInactiveInterval(int interval);
// 获取 Session 的最大不活动时间
int getMaxInactiveInterval();
// 使 Session 失效
void invalidate();
示例代码

创建和发送Session:

// 获取或创建 Session 对象
HttpSession session = request.getSession();
// 将属性设置到 Session 中
session.setAttribute("username", "admin");

获取Session:

// 获取 Session 对象
HttpSession session = request.getSession(false);
// 判断 Session 是否存在
if (session != null) {
    // 从 Session 中获取属性值
    String username = (String) session.getAttribute("username");
    System.out.println("Username: " + username);
}

八、过滤器与监听器

1. 过滤器(Filter)

过滤器是Java EE中一种用于对请求和响应进行预处理和后处理的组件。过滤器在Servlet容器中注册,可以对所有请求和响应进行拦截,用于完成一些通用的任务,比如:

  • 修改请求或响应的头信息;
  • 身份验证和访问权限控制;
  • 对请求或响应进行字符编码处理;
  • 过滤敏感数据;
  • 记录请求日志

在Servlet中,接口类javax.servlet.Filter封装了相关的方法用于实现过滤器;接口类javax.servlet.FilterConfig用于传递过滤器的配置信息,它包含了过滤器在部署描述符(xml文件)中配置的初始化参数;接口类javax.servlet.FilterChain用于管理过滤器链的执行。在过滤器的doFilter方法中,通过FilterChain可以将请求和响应传递给下一个过滤器或目标资源。

补充:在Spring框架中提供了一种叫做拦截器(Interceptor)的机制,用于拦截并处理Controller的方法调用。与Servlet的过滤器类似,但更加灵活,可以根据业务需要选择性地拦截请求。关于两者的具体区别请自行搜索。

过滤器的生命周期
  • 实例化阶段:过滤器在web应用被加载时就完成实例化。
  • 初始化阶段:完成实例化后,Servlet容器会调用void init(FilterConfig config)方法初始化过滤器,这个阶段通常用于执行一些初始化操作,读取FilterConfig对象中的配置信息等。因为一个Servlet对象在整个生命周期中只调用init()方法一次,因此拦截器的初始化操作也只会执行一次。
  • 请求处理阶段:在每次请求到达目标资源前,Servlet容器会调用过滤器的void doFilter(ServletRequest,ServlerResponse,FilterChain)方法,允许过滤器修改请求或响应,或将请求和响应传递给下一个过滤器。如果过滤器对处理后的请求执行了放行操作,那么这个请求便会发送给目标资源,否则该请求会被过滤。
  • 销毁阶段:Servlet容器在调用destory()方法后,会销毁所有过滤器。因为一个Servlet对象在整个生命周期中只调用destory()方法一次,因此拦截器的销毁操作也只会执行一次。
过滤器常用方法

javax.servlet.Filter:

// 获取过滤器的配置信息
FilterConfig getFilterConfig();
// 初始化过滤器
void init(FilterConfig filterConfig) throws ServletException;
// 执行过滤操作
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException;
// 销毁过滤器
void destroy();

javax.servlet.FilterConfig:

// 获取过滤器的名称
String getFilterName();
// 根据初始化参数的名称获取初始化参数的值
String getInitParameter(String name);
// 获取所有初始化参数的名称的枚举
Enumeration<String> getInitParameterNames();

javax.servlet.FilterChain:

// 将请求和响应传递给过滤器链中的下一个过滤器或目标资源
void doFilter(ServletRequest request, ServletResponse response)
        throws IOException, ServletException;
示例代码

com.example.MyFilter类中的代码如下:

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class MyFilter implements Filter {
    private FilterConfig filterConfig;

	// 初始化过滤器的相关逻辑
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
	    // 读取过滤器配置
        this.filterConfig = filterConfig;
        // 获取初始化参数paramName的值
        String paramValue = filterConfig.getInitParameter("paramName");

		System.out.println("过滤器已初始化,paramName的值为:" + paramValue);
    }

	// 对请求进行处理
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        long startTime = System.currentTimeMillis();

        // 执行过滤器链中的下一个过滤器或目标资源
        chain.doFilter(request, response);

        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime;

        // 记录请求的处理时间
        System.out.println("请求的处理时间为:" + executionTime + " 毫秒");
    }

	// 销毁过滤器的相关逻辑
    @Override
    public void destroy() {
        System.out.println("过滤器已被销毁");
    }
}

xml文件中的相关内容如下:

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.example.TimingFilter</filter-class>
    <init-param>
	    <param-name>paramName1</param-name>
	    <param-value>paramValue1</param-value>
	</init-param>
	<init-param>
	    <param-name>paramName2</param-name>
	    <param-value>paramValue2</param-value>
	</init-param>
</filter>

<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/login</url-pattern>
    <url-pattern>/index/*</url-pattern>
</filter-mapping>

以上代码实现了将MyFilter这个拦截器映射到此web应用的/login和以/index开头的url上,并设置了两个初始化参数。

此外,使用注解配置,我们可以将上面的xml配置简化为@WebFilter(filterName = "MyFilter", urlPatterns = {"/login", "/index/*"}, initParams = {@WebInitParam(name = "paramName1", value = "paramValue1"), @WebInitParam(name = "paramName2", value = "paramValue2")})

2. 监听器(Listener):

监听器用于监听Web应用中的事件,比如Servlet的生命周期事件、HTTP会话的创建和销毁事件等。监听器是基于观察者模式实现的,可以响应特定事件的发生,并执行相应的逻辑。常见的监听器包括:

  • ServletContextListener:监听ServletContext的生命周期事件,可用于在Web应用启动和关闭时执行一些初始化和清理操作。
  • HttpSessionListener:监听HTTP会话的创建和销毁事件,可以进行用户登录和退出的处理。
  • ServletRequestListener:监听ServletRequest的创建和销毁事件,可用于记录请求日志等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值