天天看點

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

文章目錄

    • 問題背景
    • 解決方案
    • 源碼分析

問題背景

之前跟着一個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目錄下面。

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

然後我發現配置攔截器之後,始終無法通路到靜态資源。我把注意集中在

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

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

走完這兩步可以發現我們自定義配置的

pathPatterns

locationValues

,和其他兩個是并列的。

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

2.然後我試下配置檔案的方式,比較下他們的差别。把重寫的

addResourceHandler

注釋掉,把配置檔案那句話加回去,debug打在autoconfiguration裡面。

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

最下方看到,配置裡添加的static路徑在mvcProperties中。這和預期是一緻的,因為

@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {
           

向下運作到和剛才一樣的位置。

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

它執行的兩個内部add方法會加入到registrations裡面。其中下面那個裡面會調用這個mvcProperties變量。看來關鍵就在這。

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

容易看到servletContext不為null。

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

發現這個add裡面的registration發生了改變

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)

是以這裡執行完之後registration還是兩個,隻不過我們更改了後面那個的pathPattern。

SpringBoot 2.4.5配置攔截器+通路靜态資源 源碼分析(已解決)