在Spring Boot項目中,攔截器常常被用來作登錄驗證,日誌記錄等操做。攔截器是Spring提供的,因此能夠將攔截器注成bean,由IOC容器來管理。實現攔截器的方式很簡單,主要由如下兩個步驟:java
HandlerInterceptor
接口WebMvcConfigurer
接口,添加自定義攔截器類簡要實現代碼以下:面試
自定義攔截器 LoginInterceptor
:微信
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token"); if(StringUtils.isEmpty(token)){ ... return false; } return true; } }
配置自定義攔截器:ide
@Configuration public class WebConfiguration implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) // 攔截的請求 .addPathPatterns("/**") // 不用攔截的請求 .excludePathPatterns("/login"); } }
這個攔截器的主要做用就是攔截全部訪問請求,驗證所帶token
是否有效,當token
驗證成功後,才能訪問咱們的業務接口。這時候就須要提供一個驗證token
有效性的接口,在攔截器中驗證token
,因爲攔截器是Spring提供的,所以很容易想到使用@Component
註解將攔截器注成一個 bean。而後使用@Autowired
註解將驗證token
的類注入到攔截器進行驗證。this
改造完的代碼以下:日誌
驗證token接口類:code
@Component public class TokenUtil { /** * 驗證token 是否有效 */ public boolean checkToken(String token){ ... } }
改造完的攔截器代碼以下:中間件
@Component public class LoginInterceptor implements HandlerInterceptor { @Autowired private TokenUtil tokenUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if(!tokenUtil.checkToken(token)){ ... return false; } return true; } }
調用接口時發現,TokenUtil並無被注入進來!明明代碼寫的沒問題,爲何不能正常注入TokenUtil
呢?對象
仔細觀察咱們自定義的配置類WebConfiguration
,在添加攔截器的時候用的是new LoginInterceptor()
,若是想要攔截器生效,必須將攔截器配置到WebMvc的配置類中,就是咱們自定義的WebConfiguration
類。如今添加攔截器的時候是 new 了一個攔截器,也就是說並無將攔截器託管給IOC容器,因此就沒法引入Spring的bean對象。教程
解決問題的思路也很簡單,就是將攔截器也託管給IOC容器,這樣容器內的對象就能夠相互注入了。總共有如下三種方式進行處理上述問題。
WebConfiguration
注入攔截器攔截器代碼不變,在攔截器上使用@Component
,同時在WebConfiguration
中使用@Autowired
註解將攔截器注入。
攔截器代碼:
@Component public class LoginInterceptor implements HandlerInterceptor { }
配置類代碼:
@Configuration public class WebConfiguration implements WebMvcConfigurer { @Autowired private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor); } }
WebConfiguration
將攔截器注成bean攔截器無需增長@Component
註解,在WebConfiguration
類中使用@Bean
註解將攔截器注成bean。
攔截器代碼:
public class LoginInterceptor implements HandlerInterceptor { }
配置類代碼:
@Configuration public class WebConfiguration implements WebMvcConfigurer { @Bean public LoginInterceptor loginInterceptor(){ return new LoginInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor( loginInterceptor()); } }
思路是在WebConfiguration
類中注入須要的驗證token
的業務類,而後在初始化攔截器的時候將業務類經過構造器帶入攔截器中,這樣就不用把攔截器注成Spring Bean對象了。
攔截器代碼:
public class LoginInterceptor implements HandlerInterceptor { private TokenUtil tokenUtil; public LoginInterceptor(TokenUtil tokenUtil) { this.tokenUtil = tokenUtil; } }
配置類代碼:
@Configuration public class WebConfiguration implements WebMvcConfigurer { @Autowired private TokenUtil tokenUtil; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor(tokenUtil)); } }
網上關於攔截器的代碼基本都是經過new一個攔截器進行配置的,這時候就會出現沒法注入其餘bean的狀況。不少人想固然地直接在攔截器加@Component
註解使其成爲一個bean對象。這是一種錯誤的作法。咱們須要保證的是在WebMvc配置類中添加的攔截器是Spring 的一個bean對象,也就是說咱們須要將攔截器注成一個bean,同時將這個bean添加的WebMvc配置類中。
若是以爲文章不錯,歡迎關注、點贊、收藏,大家的支持是我創做的動力,感謝你們。
若是文章寫的有問題,請不要吝惜文筆,歡迎留言指出,我會及時覈查修改。
若是你還想看到更多別的東西,能夠微信搜索「Java旅途」進行關注。「Java旅途」目前已經整理各類中間件的使用教程及各種Java相關的面試題。