spring-boot----静态资源映射规则

以前写项目,静态资源一般都是放在webapp文件夹下,使用spring initializer创建的项目根本没有webapp文件夹,但spring boot有自己的映射规则。且看分析。

一、之前所说的配置文件访问路径

  • 规则1:之前说配置文件可以放置的位置:"classpath:/META-INF/resources/",
    "classpath:/resources/",
    "classpath:/static/",
    "classpath:/public/"。
    来源自类ResourceProperties自身的一个final属性。
// 所以当前spring.resources前缀的配置可以设定与静态资源相关的参数,比如缓存时间什么的!
@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
public class ResourceProperties {
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS
       = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
}

二、另外

在spring boot的spring mvc中,相关配置都在WebMvcAutoConfiguration类里面,这也就是我们之前提到过的类自动装载类。
他有一个addResourceHandler即资源处理方法。

@Configuration
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class,
                     TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        if (!this.resourceProperties.isAddMappings()) {
            logger.debug("Default resource handling disabled");
        } else {
            Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
            CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
            if (!registry.hasMappingForPattern("/webjars/**")) {
                this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"})
                    .addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"})
                    .setCachePeriod(this
                    .getSeconds(cachePeriod)).setCacheControl(cacheControl));
            }
    
            String staticPathPattern = this.mvcProperties.getStaticPathPattern();
            if (!registry.hasMappingForPattern(staticPathPattern)) {
                this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern})
                    .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
                    .setCachePeriod(this.getSeconds(cachePeriod))
                    .setCacheControl(cacheControl));
            }
        }
    }
}
  • 规则2:所有webjars/**都去classpath:/META-INF/resources/webjars/路径找资源。
if (!registry.hasMappingForPattern("/webjars/**")) {
    this.customizeResourceHandlerRegistration(
        registry
            .addResourceHandler(new String[]{"/webjars/**"})
            .addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"})
            .setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl)
    );
}

那么何为webjars?即以jar包的方式导入静态文件。可以试试google webjars,可以进入网站https://www.webjars.org/导包。比如我已经导入的jquery包

    
       org.webjars
       jquery
       3.4.1
   

可以看到引入的webjars:


spring-boot----静态资源映射规则_第1张图片

启动spring boot直接访问localhost:8080/webjars/jquery/3.4.1/jquery.js就可以访问到这个js文件。

方法的源码向下看

String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
    this.customizeResourceHandlerRegistration(
            registry.addResourceHandler(new String[]{staticPathPattern})
                .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
                .setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}

上述源码可以看出staticPathPatterngetResourceLocations(this.resourceProperties.getStaticLocations())是映射的。
那么两者的默认值是什么呢?
ctrl点进去:可以看到this表示的WebMvcProperties类中的无参构造函数中this.staticPathPattern = "/**";。所以其对应/**。
同样ctrl点击后面的获取路径的方法:同样来到ResourceProperties类中。

public class ResourceProperties {
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS 
        = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
    private String[] staticLocations;
    
    public ResourceProperties() {
        this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
        this.addMappings = true;
        this.chain = new ResourceProperties.Chain();
        this.cache = new ResourceProperties.Cache();
    }
}

其默认构造函数将CLASSPATH_RESOURCE_LOCATIONS赋予staticLocations。所以没有特殊配置,其默认值和第final属性是一样的!

  • 规则3:/**映射{"classpath:/META-INF/resources/",
    "classpath:/resources/",
    "classpath:/static/",
    "classpath:/public/"}
    我已经在项目文件夹下创建了对应的文件夹!

三、欢迎页面

同样在WebMvcAutoConfiguration类里面的方法

public class WebMvcAutoConfiguration {
    private Optional getWelcomePage() {
        String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
        return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
    }
    
    private Resource getIndexHtml(String location) {
        return this.resourceLoader.getResource(location + "index.html");
    }
}

其中this.resourceProperties.getStaticLocations()获取的还是ResourceProperties类中的那个final属性中的路径,然后后面使用java 1.8中的流遍历将对应的路径和index.html结合获取首页地址。所以我们可以试试数组中的随便一份路径的文件夹下面创建一个index.html。
然后直接访问localhost:8080就可以访问到欢迎页面了!我已在public文件夹下面创建。

四、页面图标

在WebMvcAutoConfiguration类的最后有一个静态内部类叫做FaviconConfiguration用来配置页面图标的。
道理和前面差不多,不讲了。想要更换页面图标,只要将一个favicon.ico文件移到上述final属性所有的文件夹之一即可!

你可能感兴趣的:(spring-boot----静态资源映射规则)