SpringBoot中Servlet、Filter、Listener四種注冊(cè)方式全解析
引言
在Spring Boot項(xiàng)目里,Servlet、Filter、Listener是Java Web的核心組件,和傳統(tǒng)Java Web項(xiàng)目比起來(lái),它們的注冊(cè)方式簡(jiǎn)單了不少~ Spring Boot提供了四種便捷注冊(cè)方式,各自適配不同場(chǎng)景,下面給大家詳細(xì)說(shuō)說(shuō)每種方式的實(shí)現(xiàn)、特點(diǎn)和注意點(diǎn)。
方式一:通過(guò)Spring Bean自動(dòng)注冊(cè)(簡(jiǎn)單也簡(jiǎn)陋)
這是Spring Boot里最省事的注冊(cè)方式:Spring Boot啟動(dòng)時(shí),會(huì)自動(dòng)掃描容器里所有屬于Servlet、Filter、Listener的Spring Bean,直接把它們注冊(cè)到嵌入式Servlet容器(比如Tomcat、Jetty)里。
實(shí)現(xiàn)示例:
// 1. 注冊(cè)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. 注冊(cè)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. 注冊(cè)Listener(作為Spring Bean)
@Component
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext Initialized (Auto Registered)");
}
}
小問(wèn)題:默認(rèn)路徑的局限及優(yōu)化辦法
- Servlet:如果只有一個(gè)servlet,默認(rèn)映射路徑是/,否則為
/bean名稱(chēng)(就是類(lèi)名首字母小寫(xiě),比如上面的MyServlet,對(duì)應(yīng)路徑就是/myServlet); - Filter:默認(rèn)映射路徑是
/*,意思是會(huì)攔截所有請(qǐng)求; - Listener:不用手動(dòng)配路徑,它會(huì)自動(dòng)監(jiān)聽(tīng)Servlet上下文的相關(guān)事件(比如啟動(dòng)、銷(xiāo)毀)。
優(yōu)化小技巧:如果想改默認(rèn)路徑,要么結(jié)合方式二的RegistrationBean補(bǔ)充配置,要么直接用方式二、三、四,輕松實(shí)現(xiàn)自定義路徑~
方式二:通過(guò)RegistrationBean手動(dòng)注冊(cè)(自定義首選)
如果想對(duì)Servlet、Filter、Listener做更細(xì)致的控制——比如自定義映射路徑、設(shè)置初始化參數(shù)、指定加載順序,甚至排除某些不需要攔截的路徑,方式一就無(wú)能為力了。好在Spring Boot提供的RegistrationBean系列類(lèi),能讓我們實(shí)現(xiàn)完全自定義配置,想怎么配就怎么配。
先說(shuō)下核心類(lèi):
- ServletRegistrationBean:專(zhuān)門(mén)注冊(cè)Servlet,映射路徑、初始化參數(shù)、加載順序都能配;
- FilterRegistrationBean:注冊(cè)Filter專(zhuān)用,除了路徑,還能配攔截規(guī)則、關(guān)聯(lián)指定Servlet等;
- ServletListenerRegistrationBean:注冊(cè)Listener,能設(shè)置Listener實(shí)例和啟動(dòng)順序。
拿Filter舉個(gè)例子(其他兩種組件用法類(lèi)似):
@Configuration
public class WebConfig {
// 注冊(cè)Filter,自定義路徑和初始化參數(shù)
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter()); // 設(shè)置Filter實(shí)例
registrationBean.addUrlPatterns("/api/*"); // 自定義映射路徑(僅攔截/api下的請(qǐng)求)
registrationBean.setInitParameter("filterName", "myFilter"); // 初始化參數(shù)
registrationBean.setOrder(1); // 設(shè)置加載順序(值越小,加載越早)
return registrationBean;
}
// 注冊(cè)Servlet,自定義路徑和初始化參數(shù)
@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); // 啟動(dòng)時(shí)加載
return registrationBean;
}
// 注冊(cè)Listener
@Bean
public ServletListenerRegistrationBean<MyListener> myListenerRegistrationBean() {
ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>();
registrationBean.setListener(new MyListener());
return registrationBean;
}
}
方式三:使用@ServletRegistration和@FilterRegistration注解注冊(cè)
這是方式二(RegistrationBean手動(dòng)注冊(cè))的注解替代方案,直接用Spring Boot提供的@ServletRegistration和@FilterRegistration兩個(gè)注解,標(biāo)注在Servlet和Filter類(lèi)上,就能完成路徑、初始化參數(shù)等自定義配置,適配喜歡注解式開(kāi)發(fā)的場(chǎng)景。
核心說(shuō)明:
- @ServletRegistration:專(zhuān)門(mén)用于注冊(cè)Servlet,可配置映射路徑、啟動(dòng)加載順序、初始化參數(shù)等,功能與ServletRegistrationBean一致;
- @FilterRegistration:專(zhuān)門(mén)用于注冊(cè)Filter,可配置映射路徑、攔截規(guī)則、初始化參數(shù)等,功能與FilterRegistrationBean一致;
- 局限性:僅支持Servlet和Filter,Listener無(wú)法用這兩個(gè)注解注冊(cè),需要spring-boot 3.5.x 及以上版本。
實(shí)現(xiàn)示例:
// 用@ServletRegistration注冊(cè)Servlet,替代ServletRegistrationBean
@ServletRegistration(urlPatterns = "/myServlet/annotation", loadOnStartup = 1)
@Component
public class MyServlet extends HttpServlet {
// 實(shí)現(xiàn)邏輯...
}
// 用@FilterRegistration注冊(cè)Filter,替代FilterRegistrationBean
@FilterRegistration(urlPatterns = "/api/*", initParams = {@InitParam(name = "filterName", value = "myFilter")})
@Component
public class MyFilter implements Filter {
// 實(shí)現(xiàn)邏輯...
}
方式四:使用Servlet3.0注解配合@ServletComponentScan
Servlet3.0規(guī)范本身就提供了三個(gè)注解——@WebServlet、@WebFilter、@WebListener,直接標(biāo)注在組件類(lèi)上,就能指定路徑、名稱(chēng)這些配置。不過(guò)在Spring Boot項(xiàng)目里,得在啟動(dòng)類(lèi)上加個(gè)@ServletComponentScan注解,開(kāi)啟對(duì)這三個(gè)注解的掃描,組件才能被自動(dòng)注冊(cè)上。
示例如下:
// 1. 啟動(dòng)類(lèi)添加@ServletComponentScan,指定掃描包(可選,默認(rèn)掃描當(dāng)前包及子包)
@SpringBootApplication
@ServletComponentScan(basePackages = "com.example.web.component")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 2. 用@WebServlet注冊(cè)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注冊(cè)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注冊(cè)Listener
@WebListener
public class WebListenerDemo implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext Initialized (WebListener Annotated)");
}
}
注意事項(xiàng)
- @ServletComponentScan一定要加在Spring Boot啟動(dòng)類(lèi)上,不然掃描不到這三個(gè)注解標(biāo)注的組件;
- 這種方式和方式一不沖突,如果一個(gè)組件既加了@Component,又加了@WebServlet(等)注解,Spring Boot會(huì)優(yōu)先用@WebServlet里的配置(比如路徑);
- 需要Servlet3.0及以上版本的嵌入式容器,不過(guò)Spring Boot默認(rèn)集成的Tomcat等容器都支持。
四種方式對(duì)比及適用場(chǎng)景
| 注冊(cè)方式 | 優(yōu)點(diǎn) | 局限 | 適用場(chǎng)景 |
|---|---|---|---|
| Spring Bean自動(dòng)注冊(cè) | 配置最簡(jiǎn)單,不用寫(xiě)額外代碼,省時(shí)間 | 路徑等配置固定,不能自定義 | 快速開(kāi)發(fā)、不需要自定義配置的簡(jiǎn)單場(chǎng)景 |
| RegistrationBean手動(dòng)注冊(cè) | 配置超靈活,能完全控制組件的所有參數(shù) | 需要寫(xiě)配置類(lèi),代碼量稍微多一點(diǎn) | 需要自定義路徑、初始化參數(shù)、加載順序的復(fù)雜場(chǎng)景 |
| @ServletRegistration和@FilterRegistration注解 | 注解式配置,無(wú)需寫(xiě)配置類(lèi),比RegistrationBean更簡(jiǎn)潔 | 僅支持Servlet和Filter,不支持Listener;需要spring-boot 3.5.x及以上版本 | 偏好注解開(kāi)發(fā)、僅需注冊(cè)Servlet和Filter的場(chǎng)景 |
| Servlet3.0注解+@ServletComponentScan | 注解式配置,代碼簡(jiǎn)潔,符合Servlet規(guī)范 | 需要加掃描注解,Listener的配置比較有限 | 習(xí)慣用Servlet規(guī)范注解、需要簡(jiǎn)單自定義配置的場(chǎng)景 |
以上就是SpringBoot中Servlet、Filter、Listener四種注冊(cè)方式全解析的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Servlet、Filter、Listener注冊(cè)方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 手把手教你SpringBoot過(guò)濾器N種注冊(cè)方式
- springboot使用外置的Servlet容器步驟
- SpringBoot集成WebServlet出現(xiàn)自定義servlet請(qǐng)求失敗的問(wèn)題解決方案
- SpringBoot3整合Swagger3時(shí)出現(xiàn)Type javax.servlet.http.H的ttpServletRequest not present錯(cuò)誤解決方法
- SpringBoot項(xiàng)目中filter的兩種使用詳解
- springboot filter實(shí)現(xiàn)請(qǐng)求響應(yīng)全鏈路攔截
相關(guān)文章
Java經(jīng)典設(shè)計(jì)模式之裝飾器模式解析
這篇文章主要介紹了Java經(jīng)典設(shè)計(jì)模式之裝飾器模式解析,裝飾器模式主要解決繼承關(guān)系過(guò)于復(fù)雜的問(wèn)題,通過(guò)組合來(lái)替代繼承,指在不改變現(xiàn)有對(duì)象結(jié)構(gòu)的情況下,動(dòng)態(tài)地給該對(duì)象增加一些職責(zé)(即增加其額外功能)的模式,需要的朋友可以參考下2023-08-08
Spring Boot Maven Plugin打包異常解決方案
這篇文章主要介紹了Spring Boot Maven Plugin打包異常解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
Java中通過(guò)反射實(shí)現(xiàn)代理Proxy代碼實(shí)例
這篇文章主要介紹了Java中通過(guò)反射實(shí)現(xiàn)代理Proxy代碼實(shí)例,java實(shí)現(xiàn)代理可以通過(guò)java.lang.reflect.Proxy接口結(jié)合java.lang.reflect.InvocationHandler來(lái)實(shí)現(xiàn),需要的朋友可以參考下2023-08-08
Java實(shí)現(xiàn)異步延遲隊(duì)列的方法詳解
目前系統(tǒng)中有很多需要用到延時(shí)處理的功能,本文就為大家介紹了Java實(shí)現(xiàn)異步延遲隊(duì)列的方法,文中的示例代碼講解詳細(xì),需要的可以參考一下2023-03-03
查詢(xún)Java程序日志的實(shí)現(xiàn)方式
在Linux中查詢(xún)Java日志需定位路徑(如/var/log/、/opt/、~/, 使用find)、用tail/grep查看內(nèi)容、journalctl查系統(tǒng)服務(wù)日志、調(diào)整日志級(jí)別、監(jiān)控變化及管理日志輪轉(zhuǎn)2025-09-09
Springboot的配置文件及其優(yōu)先級(jí)說(shuō)明
文章介紹了Spring Boot的配置文件,包括application.properties和application.yml的使用,以及它們的優(yōu)先級(jí),還討論了如何通過(guò)外置配置文件覆蓋內(nèi)置配置文件,并使用@Value注解讀取自定義屬性2025-12-12

