上一篇我們學習了 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; }
- 運行測試。

注解注冊
- 創建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; } }
- 運行測試。

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
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。