springboot 靜態(tài)資源訪問原理

SpringBoot 靜態(tài)資源原理

SpringBoot啟動默認(rèn)加載  xxxAutoConfiguration 類(自動配置類)    
SpringMVC功能的自動配置類 WebMvcAutoConfiguration
所以我們就可以分析WebMvcAutoConfiguration 這個類
WebMvcAutoConfiguration.java
@Configuration(         //此類不被代理
    proxyBeanMethods = false 
)
@ConditionalOnWebApplication(   //是不是一個web的應(yīng)用, web應(yīng)用就包含SERVLET
    type = Type.SERVLET
)

//是不是包含 Servlet  DispatcherServlet WebMvcConfigurer  web應(yīng)用本身就包含
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})

//不包含  WebMvcConfigurationSupport 這個類
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
    ...
    public WebMvcAutoConfiguration() {
    } 
    
內(nèi)部類 WebMvcAutoConfiguration ->WebMvcAutoConfigurationAdapter

    
    @Configuration(
        proxyBeanMethods = false
    )
    @Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
    
    //關(guān)鍵
    //EnableConfigurationProperties  開啟綁定和 將綁定的類添加到容器
    //WebMvcProperties == "spring.mvc"
    //ResourceProperties =="spring.resources"
    //WebProperties =="spring.web"
    //此處就說明了 我們 配置文件 為什么可以生效
    @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class, WebProperties.class}) 
    
    
    
    @Order(0)
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {
        
          
    //springboot 底層的代碼 如果類只有一個構(gòu)造器
    //那么 所有的構(gòu)造器使用的類 都是在spring 的IOC容器里面獲取的
    
    public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
                
                
                this.resourceProperties = (Resources)(resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources());
                //此處就是將 一些我們?nèi)绻渲玫膶傩赃M(jìn)行賦值
                
                this.mvcProperties = mvcProperties;
                this.beanFactory = beanFactory;
                this.messageConvertersProvider = messageConvertersProvider;
                this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
                this.dispatcherServletPath = dispatcherServletPath;
                this.servletRegistrations = servletRegistrations;
                this.mvcProperties.checkConfiguration();
            }
            
    }
    
    
    
    
    
    @Bean
    @ConditionalOnMissingBean  //配置視圖解析器,此處不是重點,如果我們配置了,就不用springboot的
    public InternalResourceViewResolver defaultViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix(this.mvcProperties.getView().getPrefix());
            resolver.setSuffix(this.mvcProperties.getView().getSuffix());
            return resolver;
    }


    //靜態(tài)資源加載原理
        //重點
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
            // resourceProperties.isAddMappings  是不是默認(rèn)禁用springboot 進(jìn)行靜態(tài)資源資源管理
            
            /*
            spring:
              web:
                resources:
                  add-mappings:true 
                                     默認(rèn)值是true, 就是不禁用
            */
            
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                // 如果我們使用了webjars  這里就是說明 為什么 webjars 的靜態(tài)資源可以訪問
                // 會在每個webjars jar包里面尋找/META-INF/resources/webjars/  路徑下的文件
                //將他們 添加到spring boot 的靜態(tài)資源
                this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"); 
                
                
                /*
                spring:
                    mvc:
                        static-path-pattern: /res/**
                        如果我們配置前綴, 所以資源路徑就會編程 "/res/**"    
                */
                // this.mvcProperties.getStaticPathPattern() = "/**"    默認(rèn)的靜態(tài)資源路徑規(guī)則
                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                    /*    
                    spring:
                        web:
                            resources:
                                    static-locations: classpath:/haha/
                              如果我們配置了 靜態(tài)資源路徑,就會在我們配置的靜態(tài)資源路徑下面尋找
                              this.resourceProperties.getStaticLocations() 就成了 /haha/
                    */
                    // this.resourceProperties.getStaticLocations()  = {"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
                    //默認(rèn)值,這里就說明了為什么springBoot的靜態(tài)資源需要放到這幾個文件夾下面
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    
                    //如果使用原生的servlet,也將資源添加到原生的context下面
                    if (this.servletContext != null) {
                        ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
                        registration.addResourceLocations(new Resource[]{resource});
                    }

                });
            }
    }

歡迎頁處理規(guī)則 WebMvcAutoConfiguration.java
//HandlerMapping:處理器映射器。保存了每一個Handler能處理哪些請求。  
 @Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
     WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, 
    //將/index.html 傳入    //將前綴也傳入
    this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
    return welcomePageHandlerMapping;
}
WelcomePageHandlerMapping.java
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
    //檢測 welcomePage  /index.html 是不是存在 
    //檢測 前綴是否匹配    
    // 這里就說明了,如果我們使用了靜態(tài)資源使用的前綴,就無法匹配的默認(rèn)的歡迎頁
    if (welcomePage != null && "/**".equals(staticPathPattern)) {
        logger.info("Adding welcome page: " + welcomePage);
        //設(shè)置默認(rèn)的歡迎頁
        this.setRootViewName("forward:index.html");
    } else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) { //這里是動態(tài)資源歡迎頁,使用模板
        logger.info("Adding welcome page template: index");
        this.setRootViewName("index");
    }
}
網(wǎng)站圖標(biāo)配置
這里是瀏覽器的功能,瀏覽器會自動請求訪問/favicon.ico這個資源,如果存在瀏覽器就加上,和springboot 無關(guān)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容