文章目錄
-
- 問題背景
- 解決方案
- 源碼分析
問題背景
之前跟着一個SpringBoot2版本的視訊教程學習,但是在配置攔截器的時候,始終無法通路到靜态資源。這裡是原來的攔截器代碼:
/**
* 登入檢查
* 1.配置攔截器
* 2.把配置放在容器中
*/
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
/**
* 方法執行前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
log.info("preHandle: {}", request.getRequestURI());
if (session.getAttribute("user")==null){
//System.out.println("未登入");
request.setAttribute("msg","未登入!");
request.getRequestDispatcher("/login").forward(request, response);
return false;
}else{
return true;//放行
}
}
/**
* 方法執行後
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle: {}", request.getRequestURI());
}
/**
* 頁面渲染後
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion: {}", request.getRequestURI());
}
}
WebMvcConfigurer
接口實作類裡添加:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/login","/static/**"); //放行的請求
}
目錄結構如下:靜态資源放在/static目錄下面。
然後我發現配置攔截器之後,始終無法通路到靜态資源。我把注意集中在
addInterceptor
方法,更改
excludePathPatterns
裡面的路徑,但是都沒有取得滿意的效果。以上這些都不需要動,(實際上,springMVC的攔截器路徑怎麼配,用SpringBoot就怎麼配就可以,隻是形式不同)。解決辦法在下面。
解決方案
1.首先檢查頁面中的通路路徑是否正确:我習慣在jsp裡面寫basePath,basePath可以解決很多路徑通路錯誤的問題。
在HTML中引入thymeleaf名稱空間:
使用thymeleaf寫basePath:
這樣在HTML中引入css等檔案都可以寫成:
2.然後我嘗試在application.properties中添加靜态資源的通路路徑
發現問題解決。後來借鑒了一篇文章裡面的方法,在
WebMvcConfigurer
接口實作類裡添加:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//需要配置1:----------- 需要告知系統,這是要被當成靜态檔案的!
//第一個方法設定通路路徑字首,第二個方法設定資源路徑
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
問題也能解決。
WebMvcConfigurer
完整配置如下
package indi.huishi.admin.config;
import indi.huishi.admin.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author: Huishi
* @Date: 2021/4/28 0:23
*/
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
/**
* 添加靜态資源檔案,外部可以直接通路位址
* https://www.cnblogs.com/kangkaii/p/9023751.html
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//需要配置1:----------- 需要告知系統,這是要被當成靜态檔案的!
//第一個方法設定通路路徑字首,第二個方法設定資源路徑
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
/**
* 攔截所有請求,隻放行負責登入的兩個請求路徑
* /** 攔截所有,包括靜态資源也會被攔截
* /* 不包括靜态資源的所有路徑
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/login","/static/**"); //放行的請求
}
}
源碼分析
然後我就想看看application.properties中添加靜态資源的通路路徑和重寫配置類的差別。
1.把斷點打在重寫配置類的方法,首先執行接口實作類裡自定義的
addResourceHandler
,然後會經過
WebMvcAutoConfiguration.java
執行内部定義好的兩個
addResourceHandler
走完這兩步可以發現我們自定義配置的
pathPatterns
和
locationValues
,和其他兩個是并列的。
2.然後我試下配置檔案的方式,比較下他們的差别。把重寫的
addResourceHandler
注釋掉,把配置檔案那句話加回去,debug打在autoconfiguration裡面。
最下方看到,配置裡添加的static路徑在mvcProperties中。這和預期是一緻的,因為
@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {
向下運作到和剛才一樣的位置。
它執行的兩個内部add方法會加入到registrations裡面。其中下面那個裡面會調用這個mvcProperties變量。看來關鍵就在這。
容易看到servletContext不為null。
發現這個add裡面的registration發生了改變
是以這裡執行完之後registration還是兩個,隻不過我們更改了後面那個的pathPattern。