前言
在實際開發(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注解配置
@WebFilter時Servlet3.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ù)啟動");
}
}
啟動后,控制臺輸出:

過濾器已經(jīng)生效了。但當(dāng)注冊多個過濾器時,無法指定執(zhí)行順序的,原本使用web。xml配置過濾器時,是可指定執(zhí)行順序的,但使用@WebFilter時,沒有這個配置屬性的,所以接下來介紹下通過FilterRegistrationBean進(jìn)行過濾器的注冊。
--小技巧--(2018-08-25修訂)
- 通過過濾器的java類名稱,進(jìn)行順序的約定,比如
LogFilter和AuthFilter,此時AuthFilter就會比LogFilter先執(zhí)行,因為首字母A比L前面。
可查看具體原因:《關(guān)于@webFilter使用@Order無效問題》
FilterRegistrationBean方式
FilterRegistrationBean是springboot提供的,此類提供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即可
啟動后,效果和第一種是一樣的。

監(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,控制臺輸出

請求鏈路說明

在整個請求的過程,此一圖勝千言,希望對此有個深刻的了解,通過不同組合實現(xiàn)不同的業(yè)務(wù)功能。
總結(jié)
本章節(jié)主要介紹了常用web開發(fā)時,會用到的一些常用類,本章節(jié)對
servlet未進(jìn)行介紹,平時用的比較少,用法和配置其實和攔截器、監(jiān)聽器是類似的,再次就不闡述了。
最后
目前互聯(lián)網(wǎng)上很多大佬都有
SpringBoot系列教程,如有雷同,請多多包涵了。本文是作者在電腦前一字一句敲的,每一步都是實踐的。若文中有所錯誤之處,還望提出,謝謝。
老生常談
- 個人QQ:
499452441 - 微信公眾號:
lqdevOps

完整實例地址:chapter-7