springboot 静态资源访问原理

2021-09-02  本文已影响0人  Exception_Cui

SpringBoot 静态资源原理

SpringBoot启动默认加载  xxxAutoConfiguration 类(自动配置类)    
SpringMVC功能的自动配置类 WebMvcAutoConfiguration
所以我们就可以分析WebMvcAutoConfiguration 这个类
WebMvcAutoConfiguration.java
@Configuration(         //此类不被代理
    proxyBeanMethods = false 
)
@ConditionalOnWebApplication(   //是不是一个web的应用, web应用就包含SERVLET
    type = Type.SERVLET
)

//是不是包含 Servlet  DispatcherServlet WebMvcConfigurer  web应用本身就包含
@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() {
    } 
    
内部类 WebMvcAutoConfiguration ->WebMvcAutoConfigurationAdapter

    
    @Configuration(
        proxyBeanMethods = false
    )
    @Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
    
    //关键
    //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 底层的代码 如果类只有一个构造器
    //那么 所有的构造器使用的类 都是在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());
                //此处就是将 一些我们如果配置的属性进行赋值
                
                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;
    }


    //静态资源加载原理
        //重点
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
            // resourceProperties.isAddMappings  是不是默认禁用springboot 进行静态资源资源管理
            
            /*
            spring:
              web:
                resources:
                  add-mappings:true 
                                     默认值是true, 就是不禁用
            */
            
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                // 如果我们使用了webjars  这里就是说明 为什么 webjars 的静态资源可以访问
                // 会在每个webjars jar包里面寻找/META-INF/resources/webjars/  路径下的文件
                //将他们 添加到spring boot 的静态资源
                this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"); 
                
                
                /*
                spring:
                    mvc:
                        static-path-pattern: /res/**
                        如果我们配置前缀, 所以资源路径就会编程 "/res/**"    
                */
                // this.mvcProperties.getStaticPathPattern() = "/**"    默认的静态资源路径规则
                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                    /*    
                    spring:
                        web:
                            resources:
                                    static-locations: classpath:/haha/
                              如果我们配置了 静态资源路径,就会在我们配置的静态资源路径下面寻找
                              this.resourceProperties.getStaticLocations() 就成了 /haha/
                    */
                    // this.resourceProperties.getStaticLocations()  = {"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
                    //默认值,这里就说明了为什么springBoot的静态资源需要放到这几个文件夹下面
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    
                    //如果使用原生的servlet,也将资源添加到原生的context下面
                    if (this.servletContext != null) {
                        ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
                        registration.addResourceLocations(new Resource[]{resource});
                    }

                });
            }
    }

欢迎页处理规则 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 是不是存在 
    //检测 前缀是否匹配    
    // 这里就说明了,如果我们使用了静态资源使用的前缀,就无法匹配的默认的欢迎页
    if (welcomePage != null && "/**".equals(staticPathPattern)) {
        logger.info("Adding welcome page: " + welcomePage);
        //设置默认的欢迎页
        this.setRootViewName("forward:index.html");
    } else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) { //这里是动态资源欢迎页,使用模板
        logger.info("Adding welcome page template: index");
        this.setRootViewName("index");
    }
}
网站图标配置
这里是浏览器的功能,浏览器会自动请求访问/favicon.ico这个资源,如果存在浏览器就加上,和springboot 无关
上一篇下一篇

猜你喜欢

热点阅读