SpringBoot2.0学习笔记:(五) Spring Boot的静态资源映射

SpringBoot2.0学习笔记:(五) Spring Boot的静态资源映射

2018年09月17日 11:20:18 第二庄 阅读数:340

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/liujun03/article/details/82734403

一、静态资源的加载

Spring Boot在引入了Web模块后,就会在启动的时候自动加载与Web有关的配置,所有的配置内容可在

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration中查看。下面要说的是有关静态资源加载的逻辑。首先看一下这个类
org.springframework.boot.autoconfigure.web.ResourceProperties

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
  • 1
  • 2
  • 1
  • 2

可以看到这个类是在加载配置文件中有关静态资源的参数,比如缓存时间等。参数前缀是spring.resources

WebMvcAutoConfiguration这个类中,可以找到addResourceHandlers这个资源映射方法:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
        return;
    }
    Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    CacheControl cacheControl = this.resourceProperties.getCache()
        .getCachecontrol().toHttpCacheControl();
    if (!registry.hasMappingForPattern("/webjars/**")) {
        customizeResourceHandlerRegistration(registry
                                             .addResourceHandler("/webjars/**")
                                             .addResourceLocations("classpath:/META-INF/resources/webjars/")
                                             .setCachePeriod(getSeconds(cachePeriod))
                                             .setCacheControl(cacheControl));
    }
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {
        customizeResourceHandlerRegistration(
            registry.addResourceHandler(staticPathPattern)
            .addResourceLocations(getResourceLocations(
                this.resourceProperties.getStaticLocations()))
            .setCachePeriod(getSeconds(cachePeriod))
            .setCacheControl(cacheControl));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

webjars 方式

在其中可以看到,所有包含有/webjars/**的访问路径若没有处理器处理的话都会去classpath:/META-INF/resources/webjars/这个目录下寻找资源。

Webjars官网。

WebJars是将Web前端js和CSS等资源打包成Java的Jar包,这样在Web开发中我们可以借助Maven对这些依赖库进行管理,保证这些Web资源版本唯一性,比如jQuery、Bootstrap等。

这里写图片描述

我们在项目的pom文件引入jquery.jar:

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.3.1</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

可以展开看一下jquery-3.3.1.jar的资源结构:

这里写图片描述

可以看到,所有的资源都在classpath:/META-INF/resources/webjars/这个目录下。我们启动tomcat访问一下

localhost:8080/webjars/jquery/3.3.1/jquery.js看看能否访问的到!

这里写图片描述

很顺利的访问出来了,说明上面说的所有包含有/webjars/**的访问路径都会去classpath:/META-INF/resources/webjars/这个目录下寻找资源是没错的。

“/**”访问任何资源

接着看一下这个方法的后半部分的代码:

String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
    customizeResourceHandlerRegistration(
        registry.addResourceHandler(staticPathPattern)
        .addResourceLocations(getResourceLocations(
            this.resourceProperties.getStaticLocations()))
        .setCachePeriod(getSeconds(cachePeriod))
        .setCacheControl(cacheControl));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

String staticPathPattern = this.mvcProperties.getStaticPathPattern();这段代码得到的是"/**"这个字符串,也就是说,你访问的任何路径若是没有处理器来处理的话 ,默认会去这里来找资源:this.resourceProperties.getStaticLocations(),即:

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {

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

	/**
	 * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
	 * /resources/, /static/, /public/].
	 */
	private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/", 
"classpath:/public/"
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

我们可以尝试在项目类路径下分别建立这些文件夹,并放入一些静态资源以作访问:

这里写图片描述

在浏览器中依次访问:http://localhost:8080/111.png,确实是可以访问的到的。

二、欢迎页的加载

WebMvcAutoConfiguration这个类中,可以找到welcomePageHandlerMapping这个欢迎页映射方法:

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(
    ApplicationContext applicationContext) {
    return new WelcomePageHandlerMapping(
        new TemplateAvailabilityProviders(applicationContext),
        applicationContext, getWelcomePage(),
        this.mvcProperties.getStaticPathPattern());
}

static String[] getResourceLocations(String[] staticLocations) {
    String[] locations = new String[staticLocations.length
                                    + SERVLET_LOCATIONS.length];
    System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length);
    System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length,
                     SERVLET_LOCATIONS.length);
    return locations;
}

private Optional<Resource> 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");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

首先看一下getWelcomePage()这个方法,其逻辑就是循环各个静态资源路径,在其后匹配上index.html,然后首先在哪个静态资源路径下找到了index.html就将此index.html返回。

我们可以在classpath:/static/这个目录下新建一个index.html文件,然后直接访问localhost:8080,可以看到定位到了index.html文件。

三、应用图标的加载 favicon.ico

WebMvcAutoConfiguration这个类中,可以找到FaviconConfiguration这个图标配置的内部类:

@Configuration
@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
public static class FaviconConfiguration implements ResourceLoaderAware {

    private final ResourceProperties resourceProperties;

    private ResourceLoader resourceLoader;

    public FaviconConfiguration(ResourceProperties resourceProperties) {
        this.resourceProperties = resourceProperties;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Bean
    public SimpleUrlHandlerMapping faviconHandlerMapping() {
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
                                                   faviconRequestHandler()));
        return mapping;
    }

    @Bean
    public ResourceHttpRequestHandler faviconRequestHandler() {
        ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
        requestHandler.setLocations(resolveFaviconLocations());
        return requestHandler;
    }

    private List<Resource> resolveFaviconLocations() {
        String[] staticLocations = getResourceLocations(
            this.resourceProperties.getStaticLocations());
        List<Resource> locations = new ArrayList<>(staticLocations.length + 1);
        Arrays.stream(staticLocations).map(this.resourceLoader::getResource)
            .forEach(locations::add);
        locations.add(new ClassPathResource("/"));
        return Collections.unmodifiableList(locations);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

逻辑和欢迎页差不多,只要你将你的图标置于静态资源文件夹中,就会将你自己的favicon.ico这个图标文件作为应用程序的图标。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值