前言
在實(shí)際開發(fā)過程中,經(jīng)常會(huì)碰見一些比如系統(tǒng)啟動(dòng)初始化信息、統(tǒng)計(jì)在線人數(shù)、在線用戶數(shù)、過濾敏高詞匯、訪問權(quán)限控制(URL級(jí)別)等業(yè)務(wù)需求。這些對(duì)于業(yè)務(wù)來說一般上是無關(guān)的,業(yè)務(wù)方是無需關(guān)系的,業(yè)務(wù)只需要關(guān)系自己內(nèi)部業(yè)務(wù)的事情。所以一般上實(shí)現(xiàn)以上的功能,都會(huì)或多或少的用到今天準(zhǔn)備講解的
過濾器、監(jiān)聽器、攔截器來實(shí)現(xiàn)以上功能。
過濾器
過濾器
Filter,是Servlet的的一個(gè)實(shí)用技術(shù)了。可通過過濾器,對(duì)請(qǐng)求進(jìn)行攔截,比如讀取session判斷用戶是否登錄、判斷訪問的請(qǐng)求URL是否有訪問權(quán)限(黑白名單)等。主要還是可對(duì)請(qǐng)求進(jìn)行預(yù)處理。接下來介紹下,在springboot如何實(shí)現(xiàn)過濾器功能。
利用WebFilter注解配置
@WebFilter時(shí)Servlet3.0新增的注解,原先實(shí)現(xiàn)過濾器,需要在web.xml中進(jìn)行配置,而現(xiàn)在通過此注解,啟動(dòng)啟動(dòng)時(shí)會(huì)自動(dòng)掃描自動(dòng)注冊(cè)。
編寫Filter類:
//注冊(cè)器名稱為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 請(qǐng)求處理");
//對(duì)request、response進(jìn)行一些預(yù)處理
// 比如設(shè)置請(qǐng)求編碼
// request.setCharacterEncoding("UTF-8");
// response.setCharacterEncoding("UTF-8");
//TODO 進(jìn)行業(yè)務(wù)邏輯
//鏈路 直接傳給下一個(gè)過濾器
chain.doFilter(request, response);
}
@Override
public void destroy() {
log.info("filter 銷毀");
}
}
然后在啟動(dòng)類加入@ServletComponentScan注解即可。
@SpringBootApplication
@ServletComponentScan
@Slf4j
public class Chapter7Application {
public static void main(String[] args) {
SpringApplication.run(Chapter7Application.class, args);
log.info("chapter7 服務(wù)啟動(dòng)");
}
}
啟動(dòng)后,控制臺(tái)輸出:

過濾器已經(jīng)生效了。但當(dāng)注冊(cè)多個(gè)過濾器時(shí),無法指定執(zhí)行順序的,原本使用web。xml配置過濾器時(shí),是可指定執(zhí)行順序的,但使用@WebFilter時(shí),沒有這個(gè)配置屬性的,所以接下來介紹下通過FilterRegistrationBean進(jìn)行過濾器的注冊(cè)。
--小技巧--(2018-08-25修訂)
- 通過過濾器的java類名稱,進(jìn)行順序的約定,比如
LogFilter和AuthFilter,此時(shí)AuthFilter就會(huì)比LogFilter先執(zhí)行,因?yàn)槭鬃帜?code>A比L前面。
可查看具體原因:《關(guān)于@webFilter使用@Order無效問題》
FilterRegistrationBean方式
FilterRegistrationBean是springboot提供的,此類提供setOrder方法,可以為filter設(shè)置排序值,讓spring在注冊(cè)web filter之前排序后再依次注冊(cè)。
改寫filter
其實(shí)就輸出了@webFilter注解即可。其他的都沒有變化。
啟動(dòng)類中利用@bean注冊(cè)FilterRegistrationBean
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registration = new FilterRegistrationBean();
//當(dāng)過濾器有注入其他bean類時(shí),可直接通過@bean的方式進(jìn)行實(shí)體類過濾器,這樣不可自動(dòng)注入過濾器使用的其他bean類。
//當(dāng)然,若無其他bean需要獲取時(shí),可直接new CustomFilter(),也可使用getBean的方式。
registration.setFilter(customFilter());
//過濾器名稱
registration.setName("customFilter");
//攔截路徑
registration.addUrlPatterns("/*");
//設(shè)置順序
registration.setOrder(10);
return registration;
}
@Bean
public Filter customFilter() {
return new CustomFilter();
}
注冊(cè)多個(gè)時(shí),就注冊(cè)多個(gè)FilterRegistrationBean即可
啟動(dòng)后,效果和第一種是一樣的。

監(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)建一個(gè)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)建過濾器一樣,在啟動(dòng)類中加入@ServletComponentScan進(jìn)行自動(dòng)注冊(cè)即可。

攔截器
以上的過濾器、監(jiān)聽器都屬于Servlet的api,我們?cè)陂_發(fā)中處理利用以上的進(jìn)行過濾web請(qǐng)求時(shí),還可以使用
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:請(qǐng)求前調(diào)用");
//返回 false 則請(qǐng)求中斷
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
log.info("postHandle:請(qǐng)求后調(diào)用");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
log.info("afterCompletion:請(qǐng)求調(diào)用完成后回調(diào)方法,即在視圖渲染完成后回調(diào)");
}
}
通過繼承WebMvcConfigurerAdapter注冊(cè)攔截器
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注冊(cè)攔截器 攔截規(guī)則
//多個(gè)攔截器時(shí) 以此添加 執(zhí)行順序按添加順序
registry.addInterceptor(getHandlerInterceptor()).addPathPatterns("/*");
}
@Bean
public static HandlerInterceptor getHandlerInterceptor() {
return new CustomHandlerInterceptor();
}
}
啟動(dòng)后,訪問某個(gè)url,控制臺(tái)輸出

請(qǐng)求鏈路說明

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

個(gè)人博客:https://blog.lqdev.cn
完整實(shí)例地址:chapter-7