SpringBoot中Servlet、Filter、Listener四種注冊方式全解析
引言
在Spring Boot項目里,Servlet、Filter、Listener是Java Web的核心組件,和傳統(tǒng)Java Web項目比起來,它們的注冊方式簡單了不少~ Spring Boot提供了四種便捷注冊方式,各自適配不同場景,下面給大家詳細說說每種方式的實現(xiàn)、特點和注意點。
方式一:通過Spring Bean自動注冊(簡單也簡陋)
這是Spring Boot里最省事的注冊方式:Spring Boot啟動時,會自動掃描容器里所有屬于Servlet、Filter、Listener的Spring Bean,直接把它們注冊到嵌入式Servlet容器(比如Tomcat、Jetty)里。
實現(xiàn)示例:
// 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)");
}
}
小問題:默認路徑的局限及優(yōu)化辦法
- Servlet:如果只有一個servlet,默認映射路徑是/,否則為
/bean名稱(就是類名首字母小寫,比如上面的MyServlet,對應(yīng)路徑就是/myServlet); - Filter:默認映射路徑是
/*,意思是會攔截所有請求; - Listener:不用手動配路徑,它會自動監(jiān)聽Servlet上下文的相關(guān)事件(比如啟動、銷毀)。
優(yōu)化小技巧:如果想改默認路徑,要么結(jié)合方式二的RegistrationBean補充配置,要么直接用方式二、三、四,輕松實現(xiàn)自定義路徑~
方式二:通過RegistrationBean手動注冊(自定義首選)
如果想對Servlet、Filter、Listener做更細致的控制——比如自定義映射路徑、設(shè)置初始化參數(shù)、指定加載順序,甚至排除某些不需要攔截的路徑,方式一就無能為力了。好在Spring Boot提供的RegistrationBean系列類,能讓我們實現(xiàn)完全自定義配置,想怎么配就怎么配。
先說下核心類:
- ServletRegistrationBean:專門注冊Servlet,映射路徑、初始化參數(shù)、加載順序都能配;
- FilterRegistrationBean:注冊Filter專用,除了路徑,還能配攔截規(guī)則、關(guān)聯(lián)指定Servlet等;
- ServletListenerRegistrationBean:注冊Listener,能設(shè)置Listener實例和啟動順序。
拿Filter舉個例子(其他兩種組件用法類似):
@Configuration
public class WebConfig {
// 注冊Filter,自定義路徑和初始化參數(shù)
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter()); // 設(shè)置Filter實例
registrationBean.addUrlPatterns("/api/*"); // 自定義映射路徑(僅攔截/api下的請求)
registrationBean.setInitParameter("filterName", "myFilter"); // 初始化參數(shù)
registrationBean.setOrder(1); // 設(shè)置加載順序(值越小,加載越早)
return registrationBean;
}
// 注冊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); // 啟動時加載
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類上,就能完成路徑、初始化參數(shù)等自定義配置,適配喜歡注解式開發(fā)的場景。
核心說明:
- @ServletRegistration:專門用于注冊Servlet,可配置映射路徑、啟動加載順序、初始化參數(shù)等,功能與ServletRegistrationBean一致;
- @FilterRegistration:專門用于注冊Filter,可配置映射路徑、攔截規(guī)則、初始化參數(shù)等,功能與FilterRegistrationBean一致;
- 局限性:僅支持Servlet和Filter,Listener無法用這兩個注解注冊,需要spring-boot 3.5.x 及以上版本。
實現(xiàn)示例:
// 用@ServletRegistration注冊Servlet,替代ServletRegistrationBean
@ServletRegistration(urlPatterns = "/myServlet/annotation", loadOnStartup = 1)
@Component
public class MyServlet extends HttpServlet {
// 實現(xiàn)邏輯...
}
// 用@FilterRegistration注冊Filter,替代FilterRegistrationBean
@FilterRegistration(urlPatterns = "/api/*", initParams = {@InitParam(name = "filterName", value = "myFilter")})
@Component
public class MyFilter implements Filter {
// 實現(xiàn)邏輯...
}
方式四:使用Servlet3.0注解配合@ServletComponentScan
Servlet3.0規(guī)范本身就提供了三個注解——@WebServlet、@WebFilter、@WebListener,直接標注在組件類上,就能指定路徑、名稱這些配置。不過在Spring Boot項目里,得在啟動類上加個@ServletComponentScan注解,開啟對這三個注解的掃描,組件才能被自動注冊上。
示例如下:
// 1. 啟動類添加@ServletComponentScan,指定掃描包(可選,默認掃描當(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注冊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會優(yōu)先用@WebServlet里的配置(比如路徑);
- 需要Servlet3.0及以上版本的嵌入式容器,不過Spring Boot默認集成的Tomcat等容器都支持。
四種方式對比及適用場景
| 注冊方式 | 優(yōu)點 | 局限 | 適用場景 |
|---|---|---|---|
| Spring Bean自動注冊 | 配置最簡單,不用寫額外代碼,省時間 | 路徑等配置固定,不能自定義 | 快速開發(fā)、不需要自定義配置的簡單場景 |
| RegistrationBean手動注冊 | 配置超靈活,能完全控制組件的所有參數(shù) | 需要寫配置類,代碼量稍微多一點 | 需要自定義路徑、初始化參數(shù)、加載順序的復(fù)雜場景 |
| @ServletRegistration和@FilterRegistration注解 | 注解式配置,無需寫配置類,比RegistrationBean更簡潔 | 僅支持Servlet和Filter,不支持Listener;需要spring-boot 3.5.x及以上版本 | 偏好注解開發(fā)、僅需注冊Servlet和Filter的場景 |
| Servlet3.0注解+@ServletComponentScan | 注解式配置,代碼簡潔,符合Servlet規(guī)范 | 需要加掃描注解,Listener的配置比較有限 | 習(xí)慣用Servlet規(guī)范注解、需要簡單自定義配置的場景 |
以上就是SpringBoot中Servlet、Filter、Listener四種注冊方式全解析的詳細內(nèi)容,更多關(guān)于SpringBoot Servlet、Filter、Listener注冊方式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring Boot Maven Plugin打包異常解決方案
這篇文章主要介紹了Spring Boot Maven Plugin打包異常解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11

