只要我们的静态资源放在类路径下的/static(或/public、/resources、/META-INF/resources)下的,都可以通过“当前项目根目录/+静态资源名”的路径来访问到。
原理是:静态映射/**
对于一个请求先找Controller,如果controller不能处理才交给静态资源处理器,也找不到就报404
附可参考的springboot官方文档中Static Statement的介绍:
其中,静态资源访问默认无前缀(/**),但是可以将其放到/resources/**下统一化,为了当(mvc中提到过的)拦截器Filter能够比较方便地exclude。根据官方的reference:可以在配置的yaml/yml文件中配置以下属性static-path-pattern,自定义静态资源访问前缀:
以后就会通过“当前项目名+/resources(或者你自己定义的任何名字)/**”的路径找到静态资源。
也可以通过在yaml中修改默认静态资源的位置static-locations:(注:可以配置多个静态资源的位置,代表这些位置的静态资源都可以被访问到)
(虽然这里显示deprecated但是应该还是可以用的,因为我的版本是2.7.4较新)
要访问的是:①放在类路径下(classpath)的静态资源(static-locations)②要通过指定的路径(path)进行访问(static-path-pattern)。
首先还是要进到自动配置的依赖中:
autoconfigure包下的内容都是springboot启动application时会自动配置(auto-configured)的,一般名字为xxxAutoConfiguration类。
一个关系类图👆,其中很多都是上一篇提到的类。其中跟我们的静态资源访问有关的还要回到SpringMVC的分析中去——一个类WebMvcAutoConfiguration:
如何生效的呢?进入WebMvcAutoConfiguration,的静态内部类WebMvcAutoConfigurationAdapter(实现核心):
要特别留心@EnableConfigurationProperties这种注解,翻译过来就是“保证(自动)配置的属性”,则说明要满足这些属性才能进行(自动)配置,而且这些属性xxx与配置文件中是绑定了的。
关注这里的@EnableConfigurationProperties的两个属性(class类型的):
①WebMvcProperties.class:
WebMvcProperties=spring.mvc(与配置文件中的值对应)
②WebProperties.class:
WebProperties=spring.web(与配置文件中的值对应)
【拓展】自动配置类只有一个有参构造器的话,则其所有参数都会从容器中得到赋值:相当于多个构造器时在某一个上加@Autowared注解的意思(@Bean也同理),只不过这里只有一个就省去了。
public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
this.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();
}
构造器形参的其中两个刚好是上文的WebMvcProperties和WebProperties属性,则分别获取了跟他们两个绑定的配置文件中spring.mvc和spring.web的值。
因此回过头来看,@EnableConfigurationProperties实现的不仅是按照上文的规则绑定好①②两个关系(与配置文件对应值绑定),还要将他们注入到容器中去(@EnableConfigurationProperties加在的类@EnableConfigurationAdapter只有一个有参构造器。)
另:更多参数:
WebProperties webProperties,
WebMvcProperties mvcProperties,
ListableBeanFactory beanFactory,
ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
*ObjectProvider<DispatcherServletPath> dispatcherServletPath,
*ObjectProvider<ServletRegistrationBean<?>> servletRegistrations #*注册serlvet和filter等
ListableBeanFactory beanFactory是Spring的工厂对象BeanFactory:
ObjectProvider<HttpMessageConverters> messageConvertersProvider是找到所有的HttpMessageConverters;ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider是找到所有资源处理器的自定义器。
下面介绍关于资源处理器的实现方法addResourceHandlers
将断点放在该方法首行,debug。
可以看到它的值:
首行的this.resourceProperties是Resources类型的:
发现resourceProperties(Resources)有一个属性addMappings(默认为true),翻译也可知道是用于添加静态资源的路径映射的。在yaml中配置,发现在2.7.2的新版本中同样是deprecated的:
改为false,
禁用自动配置默认的静态资源的路径映射。又回到核心方法addResourceHandlers中分析:
另:webjars也是访问静态资源的方式之一,与jquery有关,这里不详叙。