从SpringBoot源码看资源映射原理

在谈SpringBoot之前,我们先回顾一下SSM中关于资源配置是如何实现的。

在SSM环境下,一般我们可以通过<mvc:resources />节点来配置不拦截静态资源,就像下边这样:

<mvc:resources mapping=“/js/**” location=“/js/” />

<mvc:resources mapping=“/css/**” location=“/css/” />

<mvc:resources mapping=“/img/**” location=“/img/” />

这里的/**表示的是可以匹配任意层级的路径,属于 ant风格表达式 ,感兴趣的小伙伴自行百度了解即可,所以也可以写成下面这样

<mvc:resources mapping=“/**” location=“/” />

上边的这种配置方式是属于XML配置的方式,SpringMVC的配置方式除了XML配置,也是可以通过java代码配置的,只需要我们自己定义一个类,来继WebMvcConfigurationSupport这个类即可,我们看一下WebMvcConfigurationSupport的源码部分:

/**

  • Override this method to add resource handlers for serving static resources.

  • @see ResourceHandlerRegistry

*/

protected void addResourceHandlers(ResourceHandlerRegistry registry) {

}

上边的注释写的很清楚,重写这个方法来增加一个静态资源的映射。那么具体怎么写呢?

我们再按照注释看一下ResourceHandlerRegistry的源码,重点看一下对这个类的注释,如下。

/*

To create a resource handler, use {@link #addResourceHandler(String…)} providing the URL path patterns

/ * for which the handler should be invoked to serve static resources (e.g. {@code “/resources/**”}).

大概意思就是为了创建资源的处理器,要调用addResourceHandler方法来提供url的表达式,这个方法是为了服务静态资源的(ps:英语水平也一般,了解大意即可)

然后我们去看addResourceHandler方法:

/**

  • Add a resource handler for serving static resources based on the specified URL path patterns.

  • The handler will be invoked for every incoming request that matches to one of the specified

  • path patterns.

  • Patterns like {@code "/static/**"} or {@code "/css/{filename:\\w+\\.css}"} are allowed.

  • See {@link org.springframework.util.AntPathMatcher} for more details on the syntax.

  • @return a {@link ResourceHandlerRegistration} to use to further configure the

  • registered resource handler

*/

public ResourceHandlerRegistration addResourceHandler(String… pathPatterns) {

ResourceHandlerRegistration registration = new ResourceHandlerRegistration(pathPatterns);

this.registrations.add(registration);

return registration;

}

我们看到这个方法执行后返回了一个新的类ResourceHandlerRegistration

那我们再来看一下这个类中的核心方法

/**

  • Add one or more resource locations from which to serve static content.

  • Each location must point to a valid directory. Multiple locations may

  • be specified as a comma-separated list, and the locations will be checked

  • for a given resource in the order specified.

  • For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}}

  • allows resources to be served both from the web application root and

  • from any JAR on the classpath that contains a

  • {@code /META-INF/public-web-resources/} directory, with resources in the

  • web application root taking precedence.

  • For {@link org.springframework.core.io.UrlResource URL-based resources}

  • (e.g. files, HTTP URLs, etc) this method supports a special prefix to

  • indicate the charset associated with the URL so that relative paths

  • appended to it can be encoded correctly, e.g.

  • {@code [charset=Windows-31J]https://example.org/path}.

  • @return the same {@link ResourceHandlerRegistration} instance, for

  • chained method invocation

*/

public ResourceHandlerRegistration addResourceLocations(String… resourceLocations) {

this.locationValues.addAll(Arrays.asList(resourceLocations));

return this;

}

上边注释的大意就是增加一个或者多个静态资源路径,并举了一些例子。源码我们就看到这里。

所以我们可以像这样实现资源的映射:

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**

  • @author liumeng

  • @Date: 2020/9/25 09:20

  • @Description:

*/

@Configuration

public class SpringMvcConfig extends WebMvcConfigurationSupport {

@Override

protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(“/**”).addResourceLocations(“/”);

}

}

关于SpringMVC中的资源映射部分就介绍到这,那么我们继续来看SpringBoot的资源映射吧。

SpringBoot的资源映射

===================

其实SpringBoot的资源映射也是一脉相承的,当我们初始化一个SpringBoot项目后,静态资源会默认存在resource/static目录中,那么SpringBoot的底层是怎么实现的呢,接下来我们就去源码里探索一下。

SpringBoot的源码在WebMvcAutoConfiguration这个类中,我们发现了熟悉的代码:

@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)); } }

这里面我们重点看下边这部分

String staticPathPattern = this.mvcProperties.getStaticPathPattern();

if (!registry.hasMappingForPattern(staticPathPattern)) {

customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern) .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))

.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl)); }

我们看一下getStaticPathPattern()方法的实现,发现获得的就是

/**

  • Path pattern used for static resources.

*/

private String staticPathPattern = “/**”;

这个属性的值,默认是/**。

然后我们再看this.resourceProperties.getStaticLocations()方法,发现获得的是

private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;

而CLASSPATH_RESOURCE_LOCATIONS是一个常量,值如下:

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { “classpath:/META-INF/resources/”,

“classpath:/resources/”, “classpath:/static/”, “classpath:/public/” };

在这里我们看到了四个值,static就是其中一个,到这里我们就明白了SpringBoot的静态资源为什么会存在resource/static这个目录下,而且放在以上4个目录中是都可以读取到的。

实际上SpringBoot默认的静态资源是5个,我们再来看getResourceLocations方法,如下:

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;

}

可以看到,除了我们之前看到的4个路径,这个方法里还新增了一个SERVLET_LOCATIONS的路径,点进去看一下

private static final String[] SERVLET_LOCATIONS = { “/” };

发现就是一个"/"。

所以实际上SpringBoot的默认静态资源路径有5个:

“classpath:/META-INF/resources/” , “classpath:/resources/”, “classpath:/static/”, “classpath:/public/”,“/”

自定义配置

=========

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值