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对静态资源映射、处理规则:
- 所有
/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>
- 所有
/**
,都会去以下默认路径找资源,统称为静态资源文件夹(其中"/"表示项目根目录):
- “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));
}
}
}
- 欢迎页面默认访问静态资源文件夹下的第一个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/");
}
}