springboot_4 spring boot 使用servlet,filter,listener和interceptor


上一篇我們學習了 spring boot 利用Controller響應數據與響應頁面。 一般的Web開發使用 Controller 基本上可以完成大部分需求,但是有的時候我們還是會用到 Servlet、Filter、Listener 等等。

在spring boot中添加自己的Servlet、Filter、Listener有兩種方法

  • 代碼注冊: 通過ServletRegistrationBean、 FilterRegistrationBean 和ServletListenerRegistrationBean 獲得控制。
  • 注解注冊: 在SpringBootApplication 上使用@ServletComponentScan注解后,Servlet、Filter、Listener 可以直接通過 @WebServlet、@WebFilter、@WebListener 注解自動注冊,無需其他代碼。

spring boot 中注冊servlet

代碼注冊

  • 創建Servlet類:AaServlet.java。
public class AaServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doGet"); doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doPost()"); resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.println("<h1>AaServlet</h1>"); } } 
  • 通過ServletRegistrationBean注冊。
//Project2Application.java @Bean public ServletRegistrationBean AaServletRegistration() { ServletRegistrationBean registration = new ServletRegistrationBean(new AaServlet()); registration.addUrlMappings("/a"); return registration; } 
  • 運行測試。

訪問:http://localhost:8080/a

 
測試

注解注冊

  • 創建Servlet類:BbServlet.java。
@WebServlet(urlPatterns = "/b") public class BbServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doGet"); doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doPost()"); resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.println("<h1>BbServlet</h1>"); } } 
  • 添加注解@ServletComponentScan。
@ServletComponentScan @SpringBootApplication public class Project2Application { public static void main(String[] args) { SpringApplication.run(Project2Application.class, args); } @Bean public ServletRegistrationBean AaServletRegistration() { ServletRegistrationBean registration = new ServletRegistrationBean(new AaServlet()); registration.addUrlMappings("/a"); return registration; } } 
  • 運行測試。

訪問:http://localhost:8080/b

 
測試

filter 和 listener的注冊和servlet一樣。這里就不多說了。

接下來說一下攔截器。

自定義攔截器

Spring提供了HandlerInterceptor(攔截器)。它的功能跟過濾器類似,但是提供更精細的的控制能力:在request被響應之前、request被響應之后、視圖渲染之前以及request全部結束之后。我們不能通過攔截器修改request內容,但是可以通過拋出異常(或者返回false)來暫停request的執行。

spring boot提供了一些攔截器,我們可以直接拿來使用,比如:

  • ConversionServiceExposingInterceptor
  • CorsInterceptor
  • LocaleChangeInterceptor
  • PathExposingHandlerInterceptor
  • ResourceUrlProviderExposingInterceptor
  • ThemeChangeInterceptor
  • UriTemplateVariablesHandlerInterceptor
  • UserRoleAuthorizationInterceptor

我們也可以自己定義攔截器,定義攔截器的步驟大致分為:

1、創建我們自己的攔截器類並實現 HandlerInterceptor 接口。
2、創建一個Java類繼承WebMvcConfigurerAdapter,並重寫addInterceptors 方法。
3、實例化我們自定義的攔截器,然后將對像手動添加到攔截器鏈中(在addInterceptors方法中添加)。

我們來親自試一下:

  • 創建我們自己的攔截器
//MyInterceptor2 public class MyInterceptor1 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor1==========>在請求處理之前進行調用(Controller方法調用之前)"); return true;// 只有返回true才會繼續向下執行,返回false取消當前請求 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor1==========>請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后)"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor1==========>在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)"); } } 
//MyInterceptor2 public class MyInterceptor2 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor2==========>在請求處理之前進行調用(Controller方法調用之前)"); return true;// 只有返回true才會繼續向下執行,返回false取消當前請求 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor2==========>請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后)"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor2==========>在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)"); } } 

創建一個Java類繼承WebMvcConfigurerAdapter,並重寫addInterceptors 方法,添加攔截器。

//MyWebAppConfigurer @Configuration public class MyWebAppConfigurer extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { // 多個攔截器組成一個攔截器鏈 // addPathPatterns 用於添加攔截規則 // excludePathPatterns 用戶排除攔截 registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**"); registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**"); super.addInterceptors(registry); } } 

測試:運行項目,隨便訪問一個路徑,比如http://localhost:8080/test

瀏覽器會報錯,不用管,看控制台。

 
結果

攔截器已經起作用了。

值得注意的是:只有經過DispatcherServlet 的請求,才會走攔截器鏈,我們自定義的Servlet 請求是不會被攔截的,比如我們自定義的Servlet地址是不會被攔截器攔截的。

但是過濾器不同。不管是屬於哪個Servlet 只要復合過濾器的過濾規則,過濾器都會攔截。


本篇文章就先介紹到這里,如果哪里講的不明白,請及時與我聯系。

參考文章:Spring Boot 攔截器



作者:cleverfan
鏈接:https://www.jianshu.com/p/fba5c0fd09bb
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM