SpringBoot | 第七章:過濾器、監(jiān)聽器、攔截器

前言

在實際開發(fā)過程中,經(jīng)常會碰見一些比如系統(tǒng)啟動初始化信息、統(tǒng)計在線人數(shù)、在線用戶數(shù)、過濾敏高詞匯、訪問權(quán)限控制(URL級別)等業(yè)務(wù)需求。這些對于業(yè)務(wù)來說一般上是無關(guān)的,業(yè)務(wù)方是無需關(guān)系的,業(yè)務(wù)只需要關(guān)系自己內(nèi)部業(yè)務(wù)的事情。所以一般上實現(xiàn)以上的功能,都會或多或少的用到今天準(zhǔn)備講解的過濾器、監(jiān)聽器攔截器來實現(xiàn)以上功能。

過濾器

過濾器Filter,是Servlet的的一個實用技術(shù)了。可通過過濾器,對請求進(jìn)行攔截,比如讀取session判斷用戶是否登錄、判斷訪問的請求URL是否有訪問權(quán)限(黑白名單)等。主要還是可對請求進(jìn)行預(yù)處理。接下來介紹下,在springboot如何實現(xiàn)過濾器功能。

利用WebFilter注解配置

@WebFilterServlet3.0新增的注解,原先實現(xiàn)過濾器,需要在web.xml中進(jìn)行配置,而現(xiàn)在通過此注解,啟動啟動時會自動掃描自動注冊。

編寫Filter類:

//注冊器名稱為customFilter,攔截的url為所有
@WebFilter(filterName="customFilter",urlPatterns={"/*"})
@Slf4j
public class CustomFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("filter 初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
        log.info("doFilter 請求處理");
        //對request、response進(jìn)行一些預(yù)處理
        // 比如設(shè)置請求編碼
        // request.setCharacterEncoding("UTF-8");
        // response.setCharacterEncoding("UTF-8");
        //TODO 進(jìn)行業(yè)務(wù)邏輯
        
        //鏈路 直接傳給下一個過濾器
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        log.info("filter 銷毀");
    }
}

然后在啟動類加入@ServletComponentScan注解即可。

@SpringBootApplication
@ServletComponentScan
@Slf4j
public class Chapter7Application {
    
    public static void main(String[] args) {
        SpringApplication.run(Chapter7Application.class, args);
        log.info("chapter7 服務(wù)啟動");
    }
}

啟動后,控制臺輸出:

image

過濾器已經(jīng)生效了。但當(dāng)注冊多個過濾器時,無法指定執(zhí)行順序的,原本使用web。xml配置過濾器時,是可指定執(zhí)行順序的,但使用@WebFilter時,沒有這個配置屬性的,所以接下來介紹下通過FilterRegistrationBean進(jìn)行過濾器的注冊。


--小技巧--(2018-08-25修訂)

  1. 通過過濾器的java類名稱,進(jìn)行順序的約定,比如LogFilterAuthFilter,此時AuthFilter就會比LogFilter先執(zhí)行,因為首字母AL前面。

可查看具體原因:《關(guān)于@webFilter使用@Order無效問題》


FilterRegistrationBean方式

FilterRegistrationBeanspringboot提供的,此類提供setOrder方法,可以為filter設(shè)置排序值,讓spring在注冊web filter之前排序后再依次注冊。

改寫filter

其實就輸出了@webFilter注解即可。其他的都沒有變化。

啟動類中利用@bean注冊FilterRegistrationBean

@Bean
    public FilterRegistrationBean  filterRegistrationBean() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        //當(dāng)過濾器有注入其他bean類時,可直接通過@bean的方式進(jìn)行實體類過濾器,這樣不可自動注入過濾器使用的其他bean類。
        //當(dāng)然,若無其他bean需要獲取時,可直接new CustomFilter(),也可使用getBean的方式。
        registration.setFilter(customFilter());
        //過濾器名稱
        registration.setName("customFilter");
        //攔截路徑
        registration.addUrlPatterns("/*");
        //設(shè)置順序
        registration.setOrder(10);
        return registration;
    }

    @Bean
    public Filter customFilter() {
        return new CustomFilter();
    }

注冊多個時,就注冊多個FilterRegistrationBean即可

啟動后,效果和第一種是一樣的。

image

監(jiān)聽器

Listeeshi是servlet規(guī)范中定義的一種特殊類。用于監(jiān)聽servletContext、HttpSession和servletRequest等域?qū)ο蟮膭?chuàng)建和銷毀事件。監(jiān)聽域?qū)ο蟮膶傩园l(fā)生修改的事件。用于在事件發(fā)生前、發(fā)生后做一些必要的處理。一般是獲取在線人數(shù)等業(yè)務(wù)需求。

創(chuàng)建一個ServletRequest監(jiān)聽器(其他監(jiān)聽器類似創(chuàng)建)

@WebListener
@Slf4j
public class Customlister implements ServletRequestListener{

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        log.info("監(jiān)聽器:銷毀");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        log.info("監(jiān)聽器:初始化");
    }

}

和創(chuàng)建過濾器一樣,在啟動類中加入@ServletComponentScan進(jìn)行自動注冊即可。

啟動控制臺

攔截器

以上的過濾器、監(jiān)聽器都屬于Servlet的api,我們在開發(fā)中處理利用以上的進(jìn)行過濾web請求時,還可以使用Spring提供的攔截器(HandlerInterceptor)進(jìn)行更加精細(xì)的控制。

編寫自定義攔截器類

@Slf4j
public class CustomHandlerInterceptor implements HandlerInterceptor{

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        log.info("preHandle:請求前調(diào)用");
        //返回 false 則請求中斷
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        log.info("postHandle:請求后調(diào)用");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        log.info("afterCompletion:請求調(diào)用完成后回調(diào)方法,即在視圖渲染完成后回調(diào)");

    }

}

通過繼承WebMvcConfigurerAdapter注冊攔截器

@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter{
    
    @Override
     public void addInterceptors(InterceptorRegistry registry) {
         //注冊攔截器 攔截規(guī)則
        //多個攔截器時 以此添加 執(zhí)行順序按添加順序
        registry.addInterceptor(getHandlerInterceptor()).addPathPatterns("/*");
     }
    
    @Bean
    public static HandlerInterceptor getHandlerInterceptor() {
        return new CustomHandlerInterceptor();
    }
}

啟動后,訪問某個url,控制臺輸出


控制臺

請求鏈路說明

轉(zhuǎn)至互聯(lián)網(wǎng)

在整個請求的過程,此一圖勝千言,希望對此有個深刻的了解,通過不同組合實現(xiàn)不同的業(yè)務(wù)功能。

總結(jié)

本章節(jié)主要介紹了常用web開發(fā)時,會用到的一些常用類,本章節(jié)對servlet未進(jìn)行介紹,平時用的比較少,用法和配置其實和攔截器、監(jiān)聽器是類似的,再次就不闡述了。

最后

目前互聯(lián)網(wǎng)上很多大佬都有SpringBoot系列教程,如有雷同,請多多包涵了。本文是作者在電腦前一字一句敲的,每一步都是實踐的。若文中有所錯誤之處,還望提出,謝謝。

老生常談

  • 個人QQ:499452441
  • 微信公眾號:lqdevOps
公眾號

個人博客:https://blog.lqdev.cn

完整實例地址:chapter-7

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容