zoukankan      html  css  js  c++  java
  • 关于springboot2.*版本无法加载静态资源

    前言

    在学习springboot的过程中,发现无法引用静态资源。我使用的是springboot2.2.1版本。

    追溯源码,终于解决。并记录下解决思路。

    默认加载路径

    首先得知道springboot默认加载得资源路径是什么。

    首先我们看WebMvcAutoConfiguration这个类。里面有一个方法叫做addResourceHandlers()

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
    @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
    @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
    		ValidationAutoConfiguration.class })
    public class 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();
    			
    			//所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源
    			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));
    			}
    		}
    }
    

    首先springboot会将我们classpath:/META-INF/resources/webjars/路径下的文件映射为/webjars/**

    然后再一个if判断进行静态资源文件夹映射,首先判断我们是否以使用 "/**" 做映射

    如果没有,则将"/**" 访问当前项目的任何资源,都去(如下静态资源的文件夹)找映射

    "classpath:/META‐INF/resources/",
    "classpath:/resources/",
    "classpath:/static/",
    "classpath:/public/"
    "/":当前项目的根路径
    

    什么意思呢?举一个例子,就是说默认情况下我们假如我们调用 http://localhost:8080/a.json

    Springboot就会从上面得这几个路径下去找a.json这个文件。

    问题所在

    源码也是如同猜想得这样,那为什么我的代码中,直接访问静态资源却无法做映射呢?

    我们再仔细看看WebMvcAutoConfiguration这个类。在其头上有一个这个注解:

    @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

    卧槽,瞬间恍然大悟。在我得配置文件中:

    @Configuration
    public class MyMVCConfig extends WebMvcConfigurationSupport{
        ...
    }
    

    继承了WebMvcConfigurationSupport这个类,使得springboot的自动装配失效了。因为@ConditionalOnMissingBean这个注解得作用就是,当容器中不存在这个类,如下得代码才有作用。

    为什么会这样设计呢?

    因为有时候我们得项目并不希望springboot给我们自动装配。希望完全由我们自己来配置自己来掌握。

    要想达到这个效果,springboot给我们提供了一个更为简洁得方式。

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(DelegatingWebMvcConfiguration.class)
    public @interface EnableWebMvc {
    }
    
    

    @EnableWebMvc注解会导入DelegatingWebMvcConfiguration.clss
    而DelegatingWebMvcConfiguration又继承了WebMvcConfigurationSupport

    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    

    所以当我们加上@EnableWebMvc也会有同样得效果且简洁。

    自定义配置资源映射

    springboot当然也支持我们个性化得指定映射路径,我总结了如下几个方式:

    配置类

    @Configuration
    public class MyMVCConfig extends WebMvcConfigurationSupport{
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {      
        
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");   
        }
    }
    

    上面的意思就是:将所有/static下得文件全部映射到/static/**

    配置项

    在application.properties文件中加上如下配置项

    spring.mvc.static-path-pattern=/**
    spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,
      classpath:/static/,classpath:/public/
    

    spring.mvc.static-path-pattern=/**:表示所有的访问都经过静态资源路径;

    spring.resources.static-locations:在这里配置静态资源路径。

  • 相关阅读:
    冷饭新炒:理解Sonwflake算法的实现原理
    nodejs多线程的探索和实践
    git 更新某个目录或文件
    Redis中删除过期Key的三种策略
    MySql(Innodb)事务隔离级别
    Maven的依赖范围
    Maven入门和介绍
    IDEA(Web项目忽略配置文件后)导入项目,拉取项目后的配置
    IDEA(普通项目忽略配置文件后)导入项目,拉取项目后的配置
    Maven的pom文件中标签含义
  • 原文地址:https://www.cnblogs.com/zhxiansheng/p/11933482.html
Copyright © 2011-2022 走看看