首頁技術(shù)文章正文

使用Spring Boot注冊(cè)整合方式整合Servlet三大組件

更新時(shí)間:2021-07-05 來源:黑馬程序員 瀏覽量:

IT培訓(xùn)班


在Spring Boot中,使用組件注冊(cè)方式整合內(nèi)嵌Servlet容器的Servlet、Filter、Listener三大組件時(shí),只需將這些自定義組件通過ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean類注冊(cè)到容器中即可,這些類相當(dāng)于將組件配置在web.xml中。

1. 使用組件注冊(cè)方式整合Servlet

(1)創(chuàng)建自定義Servlet類。在chapter05項(xiàng)目中創(chuàng)建名為com.itheima.servletComponent的包,并在該包下創(chuàng)建一個(gè)自定義Servlet類MyServlet,內(nèi)容如文件1所示。

文件1 MyServlet.java

     import org.springframework.stereotype.Component;
     import javax.servlet.ServletException;
     import javax.servlet.http.*;
     import java.io.IOException;
     /**
      * 自定義Servlet類
     */
     @Component
     public class MyServlet extends HttpServlet {
         @Override
         protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
                                                         throws ServletException, IOException {
             this.doPost(req, resp);
         }
         @Override
         protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
                                                          throws ServletException, IOException {
             resp.getWriter().write("hello MyServlet");
         }
     }
文件1中,使用@Component注解將MyServlet類作為組件注入Spring容器。MyServlet類繼承自HttpServlet,通過HttpServletResponse對(duì)象向頁面輸出“hello MyServlet”。

(2)創(chuàng)建Servlet組件配置類。在項(xiàng)目com.itheima.config包下創(chuàng)建一個(gè)Servlet組件配置類ServletConfig,用來對(duì)Servlet相關(guān)組件進(jìn)行注冊(cè),內(nèi)容如文件2所示。

文件2 ServletConfig.java

     import com.itheima.servletComponent.MyServlet;
     import org.springframework.boot.web.servlet.ServletRegistrationBean;
     import org.springframework.context.annotation.Bean;
     import org.springframework.context.annotation.Configuration;
     /**
      * 嵌入式Servlet容器三大組件配置
     */
     @Configuration
     public class ServletConfig {
         // 注冊(cè)Servlet組件
         @Bean
         public ServletRegistrationBean getServlet(MyServlet myServlet){
             ServletRegistrationBean registrationBean = 
                                          new ServletRegistrationBean(myServlet,"/myServlet");
             return registrationBean;
         }
     }

文件2中,使用@Configuration注解定義了一個(gè)Servlet組件配置類ServletConfig,并添加了一個(gè)getServlet(MyServlet myServlet)方法,通過組件注冊(cè)的方式注冊(cè)自定義的MyServlet組件。在注冊(cè)自定義的MyServlet組件時(shí),指定了匹配路徑為“/myServlet”,并使用@Bean注解將重新組裝的ServletRegistrationBean類對(duì)象作為Bean組件返回。

啟動(dòng)項(xiàng)目進(jìn)行測(cè)試。項(xiàng)目啟動(dòng)成功后,在瀏覽器上訪問“http://localhost:8080/myServlet”,效果如圖1所示。

組件注冊(cè)整合Servlet三大組件

圖1 自定義Servlet組件訪問效果

從圖1中可以看出,瀏覽器能夠訪問myServlet并正常顯示數(shù)據(jù),說明Spring Boot成功整合了Servlet組件。

1. 使用組件注冊(cè)方式整合Filter

(1) 創(chuàng)建自定義Filter類。在com.itheima.servletComponent包下創(chuàng)建一個(gè)類MyFilter,內(nèi)容如文件3所示。

文件3 MyFilter.java

     import org.springframework.stereotype.Component;
     import javax.servlet.*;
     import java.io.IOException;
     /**
      *  自定義Filter類
      */
     @Component
     public class MyFilter implements Filter {
         @Override
         public void init(FilterConfig filterConfig) throws ServletException {   }
         @Override
         public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                                FilterChain filterChain) throws IOException, ServletException {
             System.out.println("hello MyFilter");
             filterChain.doFilter(servletRequest,servletResponse);
         }
         @Override
         public void destroy() {   }
     }

文件3中,使用@Component注解將當(dāng)前MyFilter類作為組件注入到Spring容器中。MyFilter類實(shí)現(xiàn)Filter接口,并重寫了init()、doFilter()和destroy()方法,在doFilter()方法中向控制臺(tái)打印了“hello MyFilter”字符串。

(1) 向Servlet組件配置類注冊(cè)自定義Filter類。打開之前創(chuàng)建的Servlet組件配置類ServletConfig,將該自定義Filter類使用組件注冊(cè)方式進(jìn)行注冊(cè),示例代碼如下。

// 注冊(cè)Filter組件
@Bean
public FilterRegistrationBean getFilter(MyFilter filter){
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
    registrationBean.setUrlPatterns(Arrays.asList("/toLoginPage","/myFilter"));
    return registrationBean;
}

上述代碼中,使用組件注冊(cè)方式注冊(cè)自定義的MyFilter類。在getFilter(MyFilter filter)方法中,使用setUrlPatterns(Arrays.asList("/toLoginPage","/myFilter"))方法定義了過濾的請(qǐng)求路徑為“/toLoginPage”和“/myFilter”,同時(shí)使用@Bean注解將當(dāng)前組裝好的FilterRegistrationBean對(duì)象作為Bean組件返回。

完成Filter的自定義配置后啟動(dòng)項(xiàng)目,項(xiàng)目啟動(dòng)成功后,在瀏覽器上訪問“http://localhost:8080/myFilter”查看控制臺(tái)打印效果(由于沒有編寫對(duì)應(yīng)路徑的請(qǐng)求處理方法,所以瀏覽器會(huì)出現(xiàn)404錯(cuò)誤頁面,這里重點(diǎn)關(guān)注控制臺(tái)即可),具體如圖2所示。

組件注冊(cè)整合Servlet三大組件

圖2 自定義Filter組件訪問效果

在圖2中,瀏覽器訪問“http://localhost:8080/myFilter”時(shí)控制臺(tái)打印出了自定義Filter中定義的輸出語句“hello MyFilter”,這也就說明Spring Boot整合自定義Filter組件成功。

1. 使用組件注冊(cè)方式整合Listener

(1)創(chuàng)建自定義Listener類。在com.itheima.servletComponent包下創(chuàng)建一個(gè)類MyListener,內(nèi)容如文件4所示。

文件4 MyListener.java

     import org.springframework.stereotype.Component;
     import javax.servlet.ServletContextEvent;
     import javax.servlet.ServletContextListener;
     /**
      *  自定義Listener類
     */
     @Component
     public class MyListener implements ServletContextListener {
         @Override
         public void contextInitialized(ServletContextEvent servletContextEvent) {
             System.out.println("contextInitialized ...");
         }
         @Override
         public void contextDestroyed(ServletContextEvent servletContextEvent) {
             System.out.println("contextDestroyed ...");
         }
     }

文件4中,使用@Component注解將MyListener類作為組件注冊(cè)到Spring容器中。Listener類實(shí)現(xiàn)了ServletContextListener接口,并重寫了contextInitialized()和contextDestroyed()方法。

需要說明的是,Servlet容器提供了很多Listener接口,例如ServletRequestListener、HttpSessionListener、ServletContextListener等,我們?cè)谧远xListener類時(shí)要根據(jù)自身需求選擇實(shí)現(xiàn)這些接口,這里為了方便演示,直接實(shí)現(xiàn)了ServletContextListener接口。

(2)向Servlet組件配置類注冊(cè)自定義Listener類。打開之前創(chuàng)建的Servlet組件配置類ServletConfig,將該自定義Listener類使用組件注冊(cè)方式進(jìn)行注冊(cè),示例代碼如下。

// 注冊(cè)Listener組件
@Bean
public ServletListenerRegistrationBean getServletListener(MyListener myListener){
    ServletListenerRegistrationBean registrationBean = 
new ServletListenerRegistrationBean(myListener);
    return registrationBean;
}

上述代碼中,使用組件注冊(cè)方式注冊(cè)了一個(gè)自定義的MyListener類,在getServletListener()方法中,使用了@Bean注解將當(dāng)前組裝好的FilterRegistrationBean對(duì)象作為Bean組件返回。

完成自定義Listener組件注冊(cè)后啟動(dòng)項(xiàng)目,項(xiàng)目啟動(dòng)成功后查看控制臺(tái)打印效果,效果如圖3所示。

組件注冊(cè)整合Servlet三大組件

圖3 自定義Listener組件初始化效果

程序啟動(dòng)成功后,控制臺(tái)會(huì)打印出自定義Listener組件中定義的輸出語句“contextInitialized ...”。單擊圖中的【Exit】按鈕關(guān)閉當(dāng)前項(xiàng)目(注意,如果直接單擊紅色按鈕會(huì)強(qiáng)制關(guān)閉程序,瀏覽器就無法打印關(guān)閉監(jiān)聽信息),再次查看控制臺(tái)打印效果,效果如圖4所示。

組件注冊(cè)整合Servlet三大組件

圖4 自定義Listener組件關(guān)閉效果

程序成功關(guān)閉后,控制臺(tái)打印出了自定義Listener組件中定義的輸出語句“contextDestroyed ...”。通過效果演示,說明了Spring Boot整合自定義Listener組件成功。

細(xì)心的讀者可能發(fā)現(xiàn),將自定義的Servlet組件配置類ServletConfig全部注釋并重啟項(xiàng)目后,自定義的Servlet、Filter、Listener組件仍然生效。出現(xiàn)這種情況的主要原因是:嵌入式Servlet容器對(duì)Servlet、Filter、Listener組件進(jìn)行了自動(dòng)化識(shí)別和配置,而自定義的Servlet、Filter、Listener都繼承/實(shí)現(xiàn)了對(duì)應(yīng)的類/接口,同時(shí)自定義的Servlet、Filter、Listener組件都使用了@Component注解,這些組件會(huì)被自動(dòng)掃描為Spring組件。

使用ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean組件組裝配置的根本目的是對(duì)一些請(qǐng)求路徑和參數(shù)進(jìn)行初始化設(shè)置和組裝。假設(shè)沒有組件注冊(cè)類,那么自定義Servlet雖然生效,但無法確定生效哪個(gè)訪問路徑。自定義的Filter會(huì)對(duì)所有的請(qǐng)求都進(jìn)行過濾,不會(huì)出現(xiàn)選擇性過濾的情況。而自定義的Listener則沒有太大影響,因?yàn)槎ㄖ圃摻M件基本不需要設(shè)置什么參數(shù)。






猜你喜歡:

Spring MVC框架是什么?有什么特點(diǎn)?

Spring Boot如何定義多套不同的環(huán)境配置?

SpringBoot整合Redis來實(shí)現(xiàn)緩存技術(shù)[java培訓(xùn)]

黑馬程序員Java開發(fā)培訓(xùn)

分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!