SpringBoot原生組件注入實現(xiàn)兩種方式介紹
原生組件注入SpringBoot,即注冊 Servlet 、Filter、Listener 進入 SpringBoot
一、使用 Servlet API
使用 Servlet API 可以實現(xiàn)原生組件注入,通過在自定義 Servlet 前加入 @WebServlet
注釋,并且在 SpringBoot 啟動類前加入 @ServletComponentScan
注釋,可實現(xiàn)注冊 Servlet
代碼示例:
1、實現(xiàn)自定義 MyServlet
自定義 Servlet 類:
@WebServlet(urlPatterns = "/my") // 加入 @WebServlet 注釋 public class MyServlet extends HttpServlet { // 注意要繼承 HttpServlet 類 @Override // 重寫 DoGet 方法 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().println("haha"); } }
項目啟動類:
@ServletComponentScan(basePackages = "com.wanqing.admin") //掃描那個包中有servlet @SpringBootApplication public class DemoAdminApplication { public static void main(String[] args) { SpringApplication.run(DemoAdminApplication.class, args); } }
2、實現(xiàn)自定義 MyFilter
@Slf4j @WebFilter(urlPatterns = {"/css/*", "/images/*"}) // 攔截靜態(tài)資源 public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); log.info("MyFilter初始化完成"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { log.info("MyFilter工作"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { Filter.super.destroy(); log.info("MyFilter銷毀"); } }
3、實現(xiàn)自定義 MyServletContextListener
@WebListener @Slf4j public class MyServletContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { log.info("MyServletContextListener 監(jiān)聽到項目初始化完成"); } @Override public void contextDestroyed(ServletContextEvent sce) { log.info("MyServletContextListener 監(jiān)聽到項目銷毀"); } }
二、使用 RegistrationBean 的方式注入原生組件
通過編寫 MyRegistConfig 配置類,返回 RegistrationBean 的方式實現(xiàn)組件的注入,與上一種方式的區(qū)別在于,這種方式不需要給 自定義 Servlet 類寫 @WebServlet 注釋。
注意點:要記得使用 @Bean 注釋將 ServletRegistrationBean 注冊到容器中。
代碼示例:
自定義 MyRegistConfig 配置類,注冊 myServlet 組件,返回 ServletRegistrationBean 對象 (對象參數(shù)為自定義的 myServlet 對象實例)
myFilter 及myListener 的實現(xiàn)方式同理
@Configuration public class MyRegistConfig { @Bean public ServletRegistrationBean myServlet(){ MyServlet myServlet = new MyServlet(); return new ServletRegistrationBean(myServlet, "/my","/my02"); } @Bean public FilterRegistrationBean myFilter(){ MyFilter filter = new MyFilter(); //return new FilterRegistrationBean(filter, myServlet()); // 攔截myServlet()的路徑 FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter); filterRegistrationBean.addUrlPatterns("/my","/css/*"); return filterRegistrationBean; } @Bean public ServletListenerRegistrationBean myListener(){ MyServletContextListener myServletContextListener = new MyServletContextListener(); return new ServletListenerRegistrationBean(myServletContextListener); } }
拓展:為什么攔截器不攔截 我們自定義的 MyServlet 請求?
分析 DispatcherServlet 如何注冊進入容器中,從 DispatcherServletAutoConfiguration 類開始
容器中自動配置了 DispatcherServlet 組件,其屬性綁定到 WebMvcProperties 中,對應(yīng)的配置文件是 spring.mvc
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) // 注冊 DispatcherServlet 組件 public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) { DispatcherServlet dispatcherServlet = new DispatcherServlet(); dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest()); dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest()); dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound()); dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents()); dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails()); return dispatcherServlet; }
通過 ServletRegistrationBean < DispatcherServlet > 機制(DispatcherServletRegistrationBean.class)將 DispatcherServlet 原生的 Servlet 組件配置進來
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) { DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, webMvcProperties.getServlet().getPath()); // 拿到默認映射路徑為 / 路徑 registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup()); multipartConfig.ifAvailable(registration::setMultipartConfig); return registration; }
拿到默認映射路徑 /
WebMvcProperties.class 中配置
使用 Tomcat 做原生 Servlet 開發(fā),如果多個 Servlet 都能處理到同一層路徑,是精確優(yōu)先原則,例如:
A:/my/
B: /my/1
發(fā)送 /my/1 請求 B處理,而發(fā)送 /my/2 請求 A 處理
結(jié)論 : 來到 /my 不經(jīng)過 / —— 精確匹配 /my 直接經(jīng) Tomcat 寫出響應(yīng),不經(jīng)過 SpringMVC 的一系列流程,因此不被攔截器攔截,如下圖所示:
到此這篇關(guān)于SpringBoot原生組件注入實現(xiàn)兩種方式介紹的文章就介紹到這了,更多相關(guān)SpringBoot原生組件注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Spring Cache和Redis實現(xiàn)查詢數(shù)據(jù)緩存
在現(xiàn)代應(yīng)用程序中,查詢緩存的使用已經(jīng)變得越來越普遍,它不僅能夠顯著提高系統(tǒng)的性能,還能提升用戶體驗,在這篇文章中,我們將探討緩存的基本概念、重要性以及如何使用Spring Cache和Redis實現(xiàn)查詢數(shù)據(jù)緩存,需要的朋友可以參考下2024-07-07詳解Java編寫算法時如何加快讀寫數(shù)據(jù)速度
這篇文章主要為大家詳細介紹了Java在編寫算法時如何加快讀寫數(shù)據(jù)速度,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-03-03