Spring Boot 中Servlet、Filter、Listener 四种注册方式全解析

在Spring Boot项目里,Servlet、Filter、Listener是Java Web的核心组件,和传统Java Web项目比起来,它们的注册方式简单了不少~ Spring Boot提供了四种便捷注册方式,各自适配不同场景,下面给大家详细说说每种方式的实现、特点和注意点。

方式一:通过Spring Bean自动注册(简单也简陋)

这是Spring Boot里最省事的注册方式:Spring Boot启动时,会自动扫描容器里所有属于Servlet、Filter、Listener的Spring Bean,直接把它们注册到嵌入式Servlet容器(比如Tomcat、Jetty)里。

实现示例:

java 复制代码
// 1. 注册Servlet(作为Spring Bean)
@Component
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("MyServlet Auto Registered");
    }
}

// 2. 注册Filter(作为Spring Bean)
@Component
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("MyFilter Auto Filtering");
        chain.doFilter(request, response);
    }
}

// 3. 注册Listener(作为Spring Bean)
@Component
public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext Initialized (Auto Registered)");
    }
}

小问题:默认路径的局限及优化办法

  • Servlet:如果只有一个servlet,默认映射路径是/,否则为 /bean名称(就是类名首字母小写,比如上面的MyServlet,对应路径就是/myServlet);
  • Filter:默认映射路径是 /*,意思是会拦截所有请求;
  • Listener:不用手动配路径,它会自动监听Servlet上下文的相关事件(比如启动、销毁)。

优化小技巧:如果想改默认路径,要么结合方式二的RegistrationBean补充配置,要么直接用方式二、三、四,轻松实现自定义路径~

方式二:通过RegistrationBean手动注册(自定义首选)

如果想对Servlet、Filter、Listener做更细致的控制------比如自定义映射路径、设置初始化参数、指定加载顺序,甚至排除某些不需要拦截的路径,方式一就无能为力了。好在Spring Boot提供的RegistrationBean系列类,能让我们实现完全自定义配置,想怎么配就怎么配。

先说下核心类:

  • ServletRegistrationBean:专门注册Servlet,映射路径、初始化参数、加载顺序都能配;
  • FilterRegistrationBean:注册Filter专用,除了路径,还能配拦截规则、关联指定Servlet等;
  • ServletListenerRegistrationBean:注册Listener,能设置Listener实例和启动顺序。

拿Filter举个例子(其他两种组件用法类似):

java 复制代码
@Configuration
public class WebConfig {
    // 注册Filter,自定义路径和初始化参数
    @Bean
    public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MyFilter()); // 设置Filter实例
        registrationBean.addUrlPatterns("/api/*"); // 自定义映射路径(仅拦截/api下的请求)
        registrationBean.setInitParameter("filterName", "myFilter"); // 初始化参数
        registrationBean.setOrder(1); // 设置加载顺序(值越小,加载越早)
        return registrationBean;
    }

    // 注册Servlet,自定义路径和初始化参数
    @Bean
    public ServletRegistrationBean<MyServlet> myServletRegistrationBean() {
        ServletRegistrationBean<MyServlet> registrationBean = new ServletRegistrationBean<>();
        registrationBean.setServlet(new MyServlet());
        registrationBean.addUrlMappings("/myServlet/custom"); // 自定义映射路径
        registrationBean.setInitParameter("servletName", "myServlet");
        registrationBean.setLoadOnStartup(1); // 启动时加载
        return registrationBean;
    }

    // 注册Listener
    @Bean
    public ServletListenerRegistrationBean<MyListener> myListenerRegistrationBean() {
        ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>();
        registrationBean.setListener(new MyListener());
        return registrationBean;
    }
}

方式三:使用@ServletRegistration和@FilterRegistration注解注册

这是方式二(RegistrationBean手动注册)的注解替代方案,直接用Spring Boot提供的@ServletRegistration和@FilterRegistration两个注解,标注在Servlet和Filter类上,就能完成路径、初始化参数等自定义配置,适配喜欢注解式开发的场景。

核心说明:

  • @ServletRegistration:专门用于注册Servlet,可配置映射路径、启动加载顺序、初始化参数等,功能与ServletRegistrationBean一致;
  • @FilterRegistration:专门用于注册Filter,可配置映射路径、拦截规则、初始化参数等,功能与FilterRegistrationBean一致;
  • 局限性:仅支持Servlet和Filter,Listener无法用这两个注解注册,需要spring-boot 3.5.x 及以上版本。

实现示例:

java 复制代码
// 用@ServletRegistration注册Servlet,替代ServletRegistrationBean
@ServletRegistration(urlPatterns = "/myServlet/annotation", loadOnStartup = 1)
@Component
public class MyServlet extends HttpServlet {
    // 实现逻辑...
}

// 用@FilterRegistration注册Filter,替代FilterRegistrationBean
@FilterRegistration(urlPatterns = "/api/*", initParams = {@InitParam(name = "filterName", value = "myFilter")})
@Component
public class MyFilter implements Filter {
    // 实现逻辑...
}

方式四:使用Servlet3.0注解配合@ServletComponentScan

Servlet3.0规范本身就提供了三个注解------@WebServlet、@WebFilter、@WebListener,直接标注在组件类上,就能指定路径、名称这些配置。不过在Spring Boot项目里,得在启动类上加个@ServletComponentScan注解,开启对这三个注解的扫描,组件才能被自动注册上。

示例如下:

java 复制代码
// 1. 启动类添加@ServletComponentScan,指定扫描包(可选,默认扫描当前包及子包)
@SpringBootApplication
@ServletComponentScan(basePackages = "com.example.web.component")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// 2. 用@WebServlet注册Servlet
@WebServlet(urlPatterns = "/webServlet", name = "WebServletDemo", loadOnStartup = 1)
public class WebServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("WebServlet Annotated Registered");
    }
}

// 3. 用@WebFilter注册Filter
@WebFilter(urlPatterns = "/web/*", filterName = "WebFilterDemo")
public class WebFilterDemo implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("WebFilter Annotated Filtering");
        chain.doFilter(request, response);
    }
}

// 4. 用@WebListener注册Listener
@WebListener
public class WebListenerDemo implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext Initialized (WebListener Annotated)");
    }
}

注意事项

  • @ServletComponentScan一定要加在Spring Boot启动类上,不然扫描不到这三个注解标注的组件;
  • 这种方式和方式一不冲突,如果一个组件既加了@Component,又加了@WebServlet(等)注解,Spring Boot会优先用@WebServlet里的配置(比如路径);
  • 需要Servlet3.0及以上版本的嵌入式容器,不过Spring Boot默认集成的Tomcat等容器都支持。

四种方式对比及适用场景

注册方式 优点 局限 适用场景
Spring Bean自动注册 配置最简单,不用写额外代码,省时间 路径等配置固定,不能自定义 快速开发、不需要自定义配置的简单场景
RegistrationBean手动注册 配置超灵活,能完全控制组件的所有参数 需要写配置类,代码量稍微多一点 需要自定义路径、初始化参数、加载顺序的复杂场景
@ServletRegistration和@FilterRegistration注解 注解式配置,无需写配置类,比RegistrationBean更简洁 仅支持Servlet和Filter,不支持Listener;需要spring-boot 3.5.x及以上版本 偏好注解开发、仅需注册Servlet和Filter的场景
Servlet3.0注解+@ServletComponentScan 注解式配置,代码简洁,符合Servlet规范 需要加扫描注解,Listener的配置比较有限 习惯用Servlet规范注解、需要简单自定义配置的场景
相关推荐
晨曦中的暮雨2 小时前
限流算法——固定窗口、滑动窗口、漏桶、令牌桶
java·开发语言·算法
学长毕设3 小时前
基于SpringBoot的青少年编程学习平台系统-附源码
spring boot·学习·青少年编程
文丑颜不良啊4 小时前
LeetCode876~900题目解析
java·leetcode
aloha_7894 小时前
Java 基础、集合、异常与 JUnit 5 速查
java·junit·sqlserver
知守观5 小时前
设计模式实战:从真实老项目中看标准模板方法与工厂的落地
java·spring·设计模式
独隅5 小时前
Claude API 实战教程:从入门到完整项目
android·java·数据库·claude·claude code
Wang's Blog5 小时前
Java 项目实战: 交友项目 - 圈子功能实现:总结
java·开发语言·交友
SL_staff5 小时前
JVS私有化文档系统上线避坑指南:5大运维与业务协同断点及检测加固实践
java·开源·全栈
FinelyYang7 小时前
考试系统简答题 AI 阅卷:覆盖度驱动、异步评分与人机协同落地实践
java·大数据·人工智能
hhhjhl7 小时前
Yup 跨端三方库仓颉适配全流程
java·开发语言