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)里。

实现示例:

复制代码
// 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系列类,能让我们实现完全自定义配置,想怎么配就怎么配。

先说下核心类:

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

复制代码
@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 及以上版本。

实现示例:

复制代码
// 用@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注解,开启对这三个注解的扫描,组件才能被自动注册上。

示例如下:

复制代码
// 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规范注解、需要简单自定义配置的场景 |

相关推荐
止语Lab1 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活1 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困1 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn1 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
dkbnull1 小时前
Spring Boot请求处理组件对比详解
java·spring boot
用户298698530141 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
不能只会打代码1 小时前
Day 011 — Spring 全家桶深度拆解
spring boot·mybatis·spring aop·spring mvc·spring ioc
用户77283104908401 小时前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端
Conan在掘金1 小时前
鸿蒙报错速查:Function lacks ending return statement,返回路径漏 return 就炸,根因 + 真解法
后端
人间凡尔赛2 小时前
AI-Native 云原生架构:2026 年从容器编排到智能体编排的范式革命
后端·云原生·架构