spring?boot?2.x靜態(tài)資源會被攔截器攔截的原因分析及解決
spring boot 2.x靜態(tài)資源會被攔截器攔截的原因
在spring boot 1.5.x中,resources/static目錄下的靜態(tài)資源可以直接訪問,并且訪問路徑上不用帶static,比如靜態(tài)資源放置位置如下圖所示:
那么訪問靜態(tài)資源的路徑可以是:
http://localhost:8080/views/demoindex.html
http://localhost:8080/res/js/jquery.min.js
當有配置自定義HandlerInterceptor攔截器時,請求以上靜態(tài)資源路徑不會被攔截。
自定義HandlerInterceptor攔截器源碼如下
package com.itopener.demo.config; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; /** * @author fuwei.deng * @date 2018年4月13日 下午3:32:26 * @version 1.0.0 */ public class LoginRequiredInterceptor extends HandlerInterceptorAdapter { private final Logger logger = LoggerFactory.getLogger(LoginRequiredInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { logger.info(request.getRequestURI()); return super.preHandle(request, response, handler); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { logger.info(request.getRequestURI()); super.afterCompletion(request, response, handler, ex); } }
配置如下
package com.itopener.demo.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * @author fuwei.deng * @date 2018年4月13日 下午3:32:54 * @version 1.0.0 */ @Configuration public class WebMvcConfiguration extends WebMvcConfigurerAdapter { private final Logger logger = LoggerFactory.getLogger(WebMvcConfiguration.class); @Override public void addInterceptors(InterceptorRegistry registry) { logger.info("add interceptors"); registry.addInterceptor(new LoginRequiredInterceptor()); } }
訪問靜態(tài)資源時路徑上不用加static目錄
當spring boot版本升級為2.x時,訪問靜態(tài)資源就會被HandlerInterceptor攔截
這樣對于利用HandlerInterceptor來處理訪問權(quán)限或其他相關(guān)的功能就會受影響,跟蹤源碼查看原因,是因為spring boot 2.x依賴的spring 5.x版本,相對于spring boot 1.5.x依賴的spring 4.3.x版本而言,針對資源的攔截器初始化時有區(qū)別
具體源碼在WebMvcConfigurationSupport中,spring 4.3.x源碼如下:
/** * Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped * resource handlers. To configure resource handling, override * {@link #addResourceHandlers}. */ @Bean public HandlerMapping resourceHandlerMapping() { ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext, this.servletContext, mvcContentNegotiationManager()); addResourceHandlers(registry); AbstractHandlerMapping handlerMapping = registry.getHandlerMapping(); if (handlerMapping != null) { handlerMapping.setPathMatcher(mvcPathMatcher()); handlerMapping.setUrlPathHelper(mvcUrlPathHelper()); // 此處固定添加了一個Interceptor handlerMapping.setInterceptors(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider())); handlerMapping.setCorsConfigurations(getCorsConfigurations()); } else { handlerMapping = new EmptyHandlerMapping(); } return handlerMapping; }
而spring 5.x的源碼如下:
/** * Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped * resource handlers. To configure resource handling, override * {@link #addResourceHandlers}. */ @Bean public HandlerMapping resourceHandlerMapping() { Assert.state(this.applicationContext != null, "No ApplicationContext set"); Assert.state(this.servletContext != null, "No ServletContext set"); ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext, this.servletContext, mvcContentNegotiationManager(), mvcUrlPathHelper()); addResourceHandlers(registry); AbstractHandlerMapping handlerMapping = registry.getHandlerMapping(); if (handlerMapping != null) { handlerMapping.setPathMatcher(mvcPathMatcher()); handlerMapping.setUrlPathHelper(mvcUrlPathHelper()); // 此處是將所有的HandlerInterceptor都添加了(包含自定義的HandlerInterceptor) handlerMapping.setInterceptors(getInterceptors()); handlerMapping.setCorsConfigurations(getCorsConfigurations()); } else { handlerMapping = new EmptyHandlerMapping(); } return handlerMapping; } /** * Provide access to the shared handler interceptors used to configure * {@link HandlerMapping} instances with. This method cannot be overridden, * use {@link #addInterceptors(InterceptorRegistry)} instead. */ protected final Object[] getInterceptors() { if (this.interceptors == null) { InterceptorRegistry registry = new InterceptorRegistry(); // 此處傳入新new的registry對象,在配置類當中設(shè)置自定義的HandlerInterceptor后即可獲取到 addInterceptors(registry); registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService())); registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider())); this.interceptors = registry.getInterceptors(); } return this.interceptors.toArray(); }
從源碼當中可以看出,使用spring 5.x時,靜態(tài)資源也會執(zhí)行自定義的攔截器,因此在配置攔截器的時候需要指定排除靜態(tài)資源的訪問路徑,即配置改為如下即可:
package com.itopener.demo.config; import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author fuwei.deng * @date 2018年4月13日 下午3:32:54 * @version 1.0.0 */ @Configuration public class WebMvcConfiguration implements WebMvcConfigurer { private final Logger logger = LoggerFactory.getLogger(WebMvcConfiguration.class); @Override public void addInterceptors(InterceptorRegistry registry) { logger.info("add interceptors"); registry.addInterceptor(new LoginRequiredInterceptor()).excludePathPatterns(Arrays.asList("/views/**", "/res/**")); } }
這樣就可以和spring boot 1.5.x一樣的方式使用了。
不過從源碼當中可以看出,每個靜態(tài)資源的請求都會被自定義Interceptor攔截,只是通過訪問路徑判斷后不會執(zhí)行攔截器的內(nèi)容,所以spring 5.x相對于spring 4.3.x而言,這部分處理的性能會更低一些
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot集成Shiro實現(xiàn)動態(tài)加載權(quán)限的完整步驟
這篇文章主要給大家介紹了關(guān)于Spring Boot集成Shiro實現(xiàn)動態(tài)加載權(quán)限的完整步驟,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring Boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-09-09Java 獲取當前時間及實現(xiàn)時間倒計時功能【推薦】
這篇文章主要介紹了Java 獲取當前時間及實現(xiàn)時間倒計時功能 ,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05Springboot中@ConfigurationProperties輕松管理應(yīng)用程序的配置信息詳解
通過@ConfigurationProperties注解,可以將外部配置文件中的屬性值注入到JavaBean中,簡化了配置屬性的讀取和管理,這使得SpringBoot應(yīng)用程序中配置文件的屬性值可以映射到POJO類中,實現(xiàn)類型安全的屬性訪問,此方法避免了手動讀取配置文件屬性的需要2024-10-10Netty分布式ByteBuf使用subPage級別內(nèi)存分配剖析
這篇文章主要為大家介紹了Netty分布式ByteBuf使用subPage級別內(nèi)存分配剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-03-03解決Maven項目中 Invalid bound statement 無效的綁定問題
這篇文章主要介紹了解決Maven項目中 Invalid bound statement 無效的綁定問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Java常用類庫Apache Commons工具類說明及使用實例詳解
這篇文章主要介紹了Java常用類庫Apache Commons工具類說明及使用實例詳解,需要的朋友可以參考下2020-02-02