Servlet 三大组件详解

Servlet 三大组件详解

Servlet 三大组件是指 Servlet、Filter(过滤器)和 Listener(监听器),它们是 Java Web 应用开发的核心基础组件,各自承担着不同的职责。下面将详细介绍这三大组件的概念、生命周期、用法和应用场景。

一、Servlet

1. 基本概念

Servlet 是运行在服务器端的 Java 程序,用于处理客户端请求并生成响应。它是连接客户端和服务器端业务逻辑的桥梁,是实现动态网页的核心技术。

2. 主要作用

  • 接收请求:解析客户端发送的 HTTP 请求
  • 处理请求:执行业务逻辑处理
  • 返回响应:生成 HTTP 响应并返回给客户端

3. 生命周期

Servlet 的生命周期分为以下几个阶段:

  1. 实例化:当第一次请求 Servlet 时,Web 容器创建 Servlet 实例(单例模式)
  2. 初始化 :容器调用 init() 方法,只执行一次,用于初始化资源
  3. 服务 :每次请求都会调用 service() 方法,根据请求类型分发到 doGet()doPost() 等方法
  4. 销毁 :服务器关闭或应用卸载时,容器调用 destroy() 方法,释放资源

4. 代码示例

java 复制代码
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;

// 使用注解配置
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    
    // 构造器,只调用一次
    public HelloServlet() {
        System.out.println("1. Servlet构造器被调用");
    }
    
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        System.out.println("2. Servlet初始化");
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<h1>Hello Servlet!</h1>");
        System.out.println("3. 处理GET请求");
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 处理POST请求
        System.out.println("3. 处理POST请求");
    }
    
    @Override
    public void destroy() {
        System.out.println("4. Servlet销毁");
    }
}

5. 配置方式

注解方式(Servlet 3.0+)
java 复制代码
@WebServlet(
    name = "HelloServlet",
    urlPatterns = "/hello",
    loadOnStartup = 1 // 服务器启动时加载
)
XML 配置方式
xml 复制代码
<servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.example.HelloServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

二、Filter(过滤器)

1. 基本概念

Filter 是在客户端和服务器之间的一个过滤层,用于拦截客户端的请求和服务器的响应,实现对请求和响应的预处理和后处理。

2. 主要作用

  • 身份验证:登录验证、权限检查
  • 数据过滤:敏感词过滤、XSS 防护
  • 字符编码处理:统一设置请求和响应的字符编码
  • 日志记录:记录请求信息
  • 响应内容修改:在响应返回客户端前修改内容

3. 生命周期

Filter 的生命周期分为以下几个阶段:

  1. 初始化 :服务器启动时,容器创建 Filter 实例并调用 init() 方法,只执行一次
  2. 过滤 :每次请求被拦截时,容器调用 doFilter() 方法
  3. 销毁 :服务器关闭时,容器调用 destroy() 方法,释放资源

4. 代码示例

java 复制代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")  // 拦截所有请求
public class EncodingFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("1. Filter初始化");
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("2. 执行过滤前的处理");
        
        // 设置请求和响应的字符编码
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        
        // 放行请求,让请求继续向下执行
        chain.doFilter(request, response);
        
        System.out.println("4. 执行过滤后的处理");
    }
    
    @Override
    public void destroy() {
        System.out.println("5. Filter销毁");
    }
}

5. 配置方式

注解方式
java 复制代码
@WebFilter(
    filterName = "EncodingFilter",
    urlPatterns = {"/*"},  // 拦截所有请求
    initParams = {
        @WebInitParam(name = "encoding", value = "UTF-8")
    }
)
XML 配置方式
xml 复制代码
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.example.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

6. 过滤器链

多个过滤器可以组成过滤器链,请求会依次经过每个过滤器。过滤器的执行顺序:

  • XML 配置:按照 <filter-mapping> 标签的顺序执行
  • 注解配置:按照类名的字母顺序执行

三、Listener(监听器)

1. 基本概念

Listener 是用于监听 Web 应用中的事件并触发相应处理的组件。它可以监听 Web 应用的生命周期、Session 的创建和销毁、属性的变化等。

2. 主要类型

ServletContext 监听器
  • ServletContextListener:监听 ServletContext 的创建和销毁
  • ServletContextAttributeListener:监听 ServletContext 属性的变化
HttpSession 监听器
  • HttpSessionListener:监听 Session 的创建和销毁
  • HttpSessionAttributeListener:监听 Session 属性的变化
  • HttpSessionBindingListener:监听对象绑定到 Session 或从 Session 解绑
  • HttpSessionActivationListener:监听 Session 的活化和钝化
ServletRequest 监听器
  • ServletRequestListener:监听请求的创建和销毁
  • ServletRequestAttributeListener:监听请求属性的变化

3. 生命周期

ServletContextListener 为例:

  1. 上下文初始化 :Web 应用启动时,调用 contextInitialized() 方法
  2. 上下文销毁 :Web 应用关闭时,调用 contextDestroyed() 方法

4. 代码示例

java 复制代码
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class AppListener implements ServletContextListener {
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("1. Web应用启动,初始化上下文");
        // 可以在这里加载配置文件、初始化数据库连接池等
    }
    
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("2. Web应用关闭,销毁上下文");
        // 可以在这里释放资源,如关闭数据库连接池等
    }
}

5. 配置方式

注解方式
java 复制代码
@WebListener
XML 配置方式
xml 复制代码
<listener>
    <listener-class>com.example.AppListener</listener-class>
</listener>

四、三大组件的调用顺序

在一个完整的请求处理流程中,三大组件的调用顺序如下:

  1. 服务器启动阶段

    • Listener(ServletContextListener)→ Filter → Servlet(如果配置了 load-on-startup)
  2. 请求处理阶段

    • Listener(ServletRequestListener)→ Filter(多个按顺序)→ Servlet → Filter(反向顺序)→ Listener
  3. 服务器关闭阶段

    • Servlet → Filter → Listener(ServletContextListener)

五、在 SpringBoot 中使用三大组件

在 SpringBoot 中使用 Servlet 三大组件需要进行额外配置:

java 复制代码
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebConfig {
    
    // 注册 Servlet
    @Bean
    public ServletRegistrationBean<HelloServlet> helloServletRegistrationBean() {
        ServletRegistrationBean<HelloServlet> registrationBean = 
            new ServletRegistrationBean<>(new HelloServlet(), "/hello");
        registrationBean.setLoadOnStartup(1);
        return registrationBean;
    }
    
    // 注册 Filter
    @Bean
    public FilterRegistrationBean<EncodingFilter> encodingFilterRegistrationBean() {
        FilterRegistrationBean<EncodingFilter> registrationBean = 
            new FilterRegistrationBean<>(new EncodingFilter());
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }
    
    // 注册 Listener
    @Bean
    public ServletListenerRegistrationBean<AppListener> appListenerRegistrationBean() {
        return new ServletListenerRegistrationBean<>(new AppListener());
    }
}

六、应用场景总结

组件 主要职责 典型应用场景
Servlet 处理请求,生成响应 用户登录、数据查询、业务处理
Filter 过滤请求和响应 登录验证、字符编码处理、敏感词过滤、日志记录
Listener 监听事件,执行相应操作 应用初始化、资源加载、Session 管理、统计在线人数

七、最佳实践

  1. Servlet

    • 尽量保持 Servlet 简洁,业务逻辑封装到 Service 层
    • 合理使用 loadOnStartup 参数控制初始化时机
  2. Filter

    • 合理设置过滤范围,避免不必要的性能消耗
    • 注意过滤器链的执行顺序
    • 不要在过滤器中执行复杂的业务逻辑
  3. Listener

    • 只在需要监听事件时使用
    • 初始化资源时注意异常处理
    • 确保资源正确释放

Servlet 三大组件是 Java Web 开发的基础,理解它们的工作原理和使用方法对于构建高效、安全的 Web 应用至关重要。

相关推荐
Rust研习社2 小时前
组合真的优于继承吗?为什么 Rust 和 Go 都拥抱组合舍弃继承?
后端·rust·编程语言
IT_陈寒2 小时前
JavaScript的闭包把我坑惨了,说好的内存会自动回收呢?
前端·人工智能·后端
CaffeinePro3 小时前
Pydantic深度使用:数据校验、枚举、ORM映射
后端·fastapi
Chenyiax3 小时前
从 Chat 到 Responses:OpenAI API 抽象为什么变了?
后端
MariaH3 小时前
Koa和Express的区别
后端
MariaH3 小时前
Koa框架的使用
后端
luckdewei5 小时前
那个用 passlib 做认证的新同事,上线第一天就把用户密码写进了日志
后端
ping某6 小时前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
JustHappy6 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
uhakadotcom6 小时前
在python 的 工程化架构中 ,什么是 薄包装器层?
后端·面试·github