美文网首页
spring-boot----静态资源映射规则

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

作者: 不过意局bugyj | 来源:发表于2019-07-13 16:14 被阅读0次

    以前写项目,静态资源一般都是放在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包

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

    可以看到引入的webjars:


    启动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<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");
        }
    }
    

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

    四、页面图标

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

    相关文章

      网友评论

          本文标题:spring-boot----静态资源映射规则

          本文链接:https://www.haomeiwen.com/subject/gblmkctx.html