spring-boot静态资源的映射规则及访问配置

springboot项目如何访问webapp目录下的文件?

对于springboot项目,通常都是把静态资源放到resources目录下,这样就不需要其他配置就能够直接访问
IDEA中若需要添加webapp资源目录并且要能够被访问,则需要做一些额外的配置

1.创建webapp资源目录

在springboot项目中,当需要在src/main目录下创建webapp目录:首先需要进行如下设置

Project Structure----Project Settings----Facets,在项目名上右键新建web

然后点击已添加的web设置Web Resource Directory,将目录设置为src/main/webapp

2.配置插件

springboot启动后对于webapp目录下的文件有时碰到无法访问的情况

由于spring默认会到classpath:/META-INF/resources/路径下找资源

所以可以在pom.xml文件中添加如下内容来解决,表示编译的时候将webapp目录中所有文件输出到META-INF/resources目录中

<build>
		<resources>
			<resource>
				<directory>src/main/webapp</directory>
				<!--在此目录下才能被访问到-->
				<targetPath>META-INF/resources</targetPath>
				<includes>
					<include>**/**</include>
				</includes>
			</resource>
		</resources>
</build>
<build>
		<resources>
			<resource>
				<directory>src/main/webapp</directory>
				<!--在此目录下才能被访问到-->
				<targetPath>META-INF/resources</targetPath>
				<includes>
					<include>**/**</include>
				</includes>
			</resource>
		</resources>
</build>

其他解决办法:

pom文件引入 插件 maven-resources-plugin 的 copy-resources插件,然后按照下面这样配置下,就可以轻松访问了

 <!--拷贝资源文件 copy-resources-->
<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <executions> 
        <execution>
            <id>copy-public</id>
            <phase>package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <directory>src/main/webapp/public</directory>
                    </resource>
                </resources>  
                <outputDirectory>${project.build.directory}/public</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

静态资源的映射规则

静态资源的配置主要关注自动配置类WebMvcAutoConfiguration

``org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#addResourceHandlers`

addResourceHandlers方法包含了springboot对静态资源映射、处理规则:

  1. 所有/webjars/** ,都去 classpath:/META-INF/resources/webjars/找资源;其中webjars是以jar包的方式引入静态资源,例如pom.xml中引入静态资源(webjar介绍:https://www.webjars.org/):
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.5.1</version>
</dependency>
  1. 所有/**,都会去以下默认路径找资源,统称为静态资源文件夹(其中"/"表示项目根目录):
  • “classpath:/META-INF/resources/”,
  • “classpath:/resources/”,
  • “classpath:/static/”,
  • “classpath:/public/”,
  • “/”

还可以在application.properties中指定静态资源的访问位置:

spring.resources.static-locations=classpath:/user/,classpath:/other

当这样做的时候,只会到指定的位置去查找,此时以上默认访问路径失效

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();
       //springboot容器中没有/webjars/**,则默认访问类路径:/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));
        }
        //方法getStaticPathPattern()默认值: "/**";    
        //方法getStaticLocations()默认值:{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/","/"};
        String staticPathPattern = this.mvcProperties.getStaticPathPattern();
        //springboot容器中没有匹配的url映射,再到这些类路径下访问:classpath:/META-INF/resources/ ...
        if (!registry.hasMappingForPattern(staticPathPattern)) {
            this.customizeResourceHandlerRegistration(
                registry.addResourceHandler(new String[]{staticPathPattern}).
                addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
        }

    }
}

  1. 欢迎页面默认访问静态资源文件夹下的第一个index.html,映射使用的是"/**"
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
   //getWelcomePage获取欢迎页面
    WelcomePageHandlerMapping welcomePageHandlerMapping =
        new WelcomePageHandlerMapping(
        new TemplateAvailabilityProviders(applicationContext),
        applicationContext, 
        this.getWelcomePage(),
        this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
    return welcomePageHandlerMapping;
}

private Optional<Resource> getWelcomePage() {
    //欢迎页到静态资源文件夹下获取,通过 getIndexHtml方法取到第一个index.html
    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");
}

配置静态资源的映射规则

静态资源的映射一般默认不用修改,如果需要可有两种方法:

方式1:一种是直接在applicaiton.xml中配置

这种办法可能会将默认的映射规则覆盖

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

方式2:在继承WebMvcConfigurer接口的配置中自定义映射规则

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    /** 
     * 默认在不配置的情况下对于/static/xxx.html这样的请求是匹配不到的,只能匹配/xxx.html
     * 添加一个匹配规则让其都能够访问
     **/
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //addResourceLocations:指的是内部文件放置的目录
        //addResoureHandler指的是对外暴露的访问路径
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }
}
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值