今天作項目的時候,發現每次攔截器日誌都會打兩遍,很納悶,懷疑是Filter被執行了兩遍。結果debug以後發現還真是!記錄一下這個神奇的BUG!java
項目中使用的是Spring-security做爲權限框架,而後作了一個JwtAuthenticationTokenFilter
做爲攔截器攔截請求,校驗Token,可是每次請求都會打兩遍日誌。下面是精簡的源代碼:spring
自定義的Filter類segmentfault
@Slf4j @Component public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { @Override protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { //...省略 //打出兩遍日誌的地方 log.info("User:{} request path:{}, method:{}, param:{}", username, request.getServletPath(), request.getMethod(), request.getParameterMap() == null ? null : OBJECT_MAPPER.writeValueAsString(request.getParameterMap())); //...省略 chain.doFilter(request, response); } }
WebSecurityConfig配置類mvc
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { //...省略 @Bean public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { return new JwtAuthenticationTokenFilter(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { //...省略 //把JwtAuthenticationTokenFilter加入到RememberMeAuthenticationFilter以前 httpSecurity.addFilterBefore(authenticationTokenFilterBean(), RememberMeAuthenticationFilter.class); } //...省略 }
請求日誌以下:框架
把自定義FilterJwtAuthenticationTokenFilter
的@Component
取消掉就能夠了,不讓它被Spring容器管理。ide
在spring容器託管的OncePerRequestFilter的bean,都會自動加入到servlet的filter chain,而上面的定義,還額外把filter加入到了spring security的
ememberMeAuthenticationFilter以前。而spring security也是一系列的filter,在mvc的filter以前執行。所以在鑑權經過的狀況下,就會前後各執行一次。debug