SpringBoot-Web 静态资源映射规则

SpringBoot当然可以存放页面、图片等静态资源,但这些静态资源放在哪个文件中,又如何去访问它们呢?可以用源码来解读:
先进入WebMvcAutoConfiguration类中,这个类包含了SpringMVC的web配置,其中有一个addResourceHandlers()方法:

        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(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }
            }
        }

可以看到首先调方法isAddMappings()判断是否做了新增映射,点进这个方法:

public boolean isAddMappings() {
    return this.addMappings;
}

这个方法属于ResourceProperties类,在看这个类的属性与构造:

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

    public ResourceProperties() {
        this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
        this.addMappings = true;
        this.chain = new ResourceProperties.Chain();
        this.cache = new ResourceProperties.Cache();
    }

发现在构造ResourceProperties类时addMappings属性就已经置为了true,所以之前WebMvcAutoConfiguration类的addResourceHandlers方法直接进入else代码块,并且registry调用addResourceHandler()新增了一个资源处理器,所有的/webjars/**都要去classpath:/META-INF/resources/webjars/这个路径下找资源,webjars本质就是以jar包的方式引入静态资源,可以引入
webjars中的jquery依赖:

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.3.1</version>
</dependency>

导入依赖后发现在外部包中存在:
在这里插入图片描述
再回到ResourceProperties类中,ResourceProperties类中的第一个属性CLASSPATH_RESOURCE_LOCATIONS:

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

与ResourceProperties类中appendSlashIfNecessary()方法:

    private String[] appendSlashIfNecessary(String[] staticLocations) {
        String[] normalized = new String[staticLocations.length];

        for(int i = 0; i < staticLocations.length; ++i) {
            String location = staticLocations[i];
            normalized[i] = location.endsWith("/") ? location : location + "/";
        }

        return normalized;
    }

表明有五个路径指向可以存放静态资源的位置,第五个是项目根目录下:

  1. “classpath:/META-INF/resources/”
  2. “classpath:/resources/”
  3. “classpath:/static/”
  4. “classpath:/public/”
  5. “/”

而且访问优先级先从 classpath:/resources/ ==> classpath:/static/ ==> “classpath:/public/”
静态资源的存放路径清楚后,可以看到WebMvcAutoConfiguration类中有welcomePageHandlerMapping()欢迎页面的映射方法:

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
return welcomePageHandlerMapping;
}

里面有一个getWelcomePage()方法,再点进去:

private Optional<Resource> getWelcomePage() {
    String[] locations = WebMvcAutoConfiguration.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");
}

getWelcomePage()方法当中调用了getIndexHtml()方法,获取index页面,可得出结论:静态资源下的所有index页面被/**所映射,在浏览器访问localhost:8080/后会直接跳转到静态文件目录下的index.html。

如果在全局配置当中配置了:

spring.resources.static-locations=classpath:xxx

默认的配置全部失效,只认自己配置的静态资源目录。

发布了12 篇原创文章 · 获赞 3 · 访问量 246

猜你喜欢

转载自blog.csdn.net/qq_38599840/article/details/104145145
今日推荐