Spring引导不提供静态内容

我无法让Spring-boot项目提供静态内容。

我在src/main/resources下放置了一个名为static的文件夹。其中有一个名为images的文件夹。当我将应用程序打包并运行时,它无法找到我放在该文件夹中的图像。

我已经尝试将静态文件放在publicresourcesMETA-INF/resources中,但没有任何工作。

如果我jar -tvf app.jar,我可以看到文件在右边文件夹的jar中: 例如,/static/images/head.png,但调用:http://localhost:8080/images/head.png,我得到的是一个404

知道为什么弹簧靴找不到这个吗?(我使用1.1.4 BTW)

221166 次浏览

你检查了Spring Boot参考文档吗?

默认情况下,Spring Boot将提供来自类路径中名为/static(或/public/resources/META-INF/resources)的文件夹或来自ServletContext根的静态内容。

你也可以将你的项目与指南使用Spring MVC服务Web内容进行比较,或者查看spring-boot-sample-web-ui项目的源代码。

如上所述,文件应该在$ClassPath/static/images/name.png, (/static或/public或/resources或/META-INF/resources)。这个$ClassPath表示main/resourcesmain/java目录。

如果你的文件不在标准dirs中,你可以添加以下配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/lib/**"); // like this
}


@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// ... etc.
}
...

与spring-boot状态不同,要获得我的spring-boot jar来提供内容: 我必须通过这个配置类添加专门注册我的src/main/resources/static内容:

@Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer {


private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };


@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
}

配置方法如下:

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {


// specific project configuration


}

重要的是,你的WebMvcConfig 五月覆盖了addResourceHandlers方法,因此你需要显式地调用super.addResourceHandlers(registry)(如果你对默认资源位置感到满意,你不需要覆盖任何方法)。

这里需要注释的另一件事是,这些默认资源位置(/static/public/resources/META-INF/resources)只有在还没有映射到/**的资源处理程序时才会被注册。

从这一刻起,如果你在src/main/resources/static/images上有一个名为image.jpg的映像,例如,你可以使用以下URL访问它:http://localhost:8080/images/image.jpg(是在端口8080上启动的服务器,应用程序部署到根上下文)。

我也遇到了类似的问题,结果证明简单的解决方案是让我的配置类扩展WebMvcAutoConfiguration:

@Configuration
@EnableWebMvc
@ComponentScan
public class ServerConfiguration extends WebMvcAutoConfiguration{
}

我不需要任何其他代码来允许我的静态内容被服务,但是,我确实在src/main/webapp下放置了一个名为public的目录,并配置maven指向src/main/webapp作为资源目录。这意味着public被复制到target/classes中,因此在运行时位于spring-boot/tomcat可以找到的类路径上。

有同样的问题,使用gradle和eclipse,并花了几个小时试图解决它。

不需要编码,诀窍是你必须使用菜单选项New->Source Folder(不是New-> Folder)来创建src/main/resources下的静态文件夹。不知道为什么这样工作,但做了new ->源文件夹然后我命名为静态文件夹(然后源文件夹对话框给出一个错误,你必须检查:更新排除过滤器在其他源文件夹解决嵌套)。我的新静态文件夹添加了index.html,现在它工作了。

寻找映射到“/”或没有映射路径的控制器。

我就遇到过这样的问题,犯了405个错误,我的头狠狠地撞了好几天。问题原来是一个带有@RestController注释的控制器,我忘记用@RequestMapping注释来注释它。我猜这个映射路径默认为“/”,并阻止了静态内容资源映射。

不是说过了一年多才让死人复活,但之前所有的答案都忽略了一些关键点:

  1. 你的类上的@EnableWebMvc将禁用org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration。如果你想要完全控制,这很好,但否则,这就是一个问题。

  2. 除了已经提供的位置之外,不需要编写任何代码为静态资源添加另一个位置。从v1.3.0查看org.springframework.boot.autoconfigure.web.ResourceProperties。RELEASE时,我看到一个字段staticLocations,可以在application.properties中配置。以下是来自源代码的片段:

    /**
    * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
    * /resources/, /static/, /public/] plus context:/ (the root of the servlet context).
    */
    private String[] staticLocations = RESOURCE_LOCATIONS;
    
  3. 如前所述,请求URL将被解析到这些位置。因此,当请求URL为/index.html时,将提供src/main/resources/static/index.html。在Spring 4.1中,负责解析路径的类是org.springframework.web.servlet.resource.PathResourceResolver

  4. 后缀模式匹配在默认情况下是启用的,这意味着对于请求URL /index.html, Spring将寻找与/index.html对应的处理程序。如果目的是提供静态内容,这就会出现问题。要禁用它,扩展WebMvcConfigurerAdapter(但不使用@EnableWebMvc)并覆盖configurePathMatch,如下所示:

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
    super.configurePathMatch(configurer);
    
    
    configurer.setUseSuffixPatternMatch(false);
    }
    

恕我直言,在代码中减少错误的唯一方法就是不要尽可能地编写代码。使用已经提供的东西,即使这需要一些研究,但回报是值得的。

2021年7月编辑:

  1. WebMvcConfigurerAdapter自Spring 5以来已弃用。实现WebMvcConfigurer并使用@Configuration进行注释。

这个解决方案对我来说很有效:

首先,在webapp/WEB-INF下放置一个资源文件夹,如下图所示

-- src
-- main
-- webapp
-- WEB-INF
-- resources
-- css
-- image
-- js
-- ...

第二,在spring配置文件中

@Configuration
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter{


@Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
return resolver;
}


@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}


@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resource/**").addResourceLocations("WEB-INF/resources/");
}
}

然后,您可以访问您的资源内容,例如 http://localhost:8080/resource/image/yourimage.jpg < / p >

我使用1.3.5,并通过Jersey实现托管一堆rest服务。在我决定添加一些html + js文件之前,这一切都很好。 这个论坛上给出的答案对我没有任何帮助。然而,当我在pom.xml中添加以下依赖项时,src / main /资源/静态的中的所有内容最终通过浏览器显示:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<dependency>

spring-web / spring-webmvc似乎是使spring引导自动配置开启的重要传递依赖项。

我认为前面的回答很好地解决了这个问题。然而,我要补充的是,在一种情况下,当你在应用程序中启用了Spring Security时,你可能必须特别告诉Spring允许对其他静态资源目录的请求,例如“静态/字体”

在我的情况下,我有“/static/css”,“/static/js”,“/static/images”默认允许,但/static/fonts/**被我的Spring安全实现阻塞。

下面是我如何解决这个问题的示例。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.....
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/fonts/**").permitAll().
//other security configuration rules
}
.....
}

如果从IDE中启动应用程序时出现问题(即从Eclipse或IntelliJ Idea启动),并使用Maven,解决方案的关键在弹簧靴开始文档中:

如果你正在使用Maven,执行:

mvn package && java -jar target/gs-spring-boot-0.1.0.jar

其中重要的部分是在应用程序实际启动之前添加package目标。(想法:Run菜单,Edit Configrations...Add,选择Run Maven Goal,并在字段中指定package目标)

有两件事需要考虑(Spring Boot v1.5.2.RELEASE)- 1)检查所有控制器类的@EnableWebMvc注释,如果有的话删除它 2)检查使用注释的Controller类- @RestController或@Controller。不要将Rest API和MVC行为混合在一个类中。对于MVC使用@Controller,对于REST API使用@RestController

以上两件事解决了我的问题。现在我的春季引导加载静态资源没有任何问题。 @Controller => load index.html =>加载静态文件
@Controller
public class WelcomeController {


// inject via application.properties
@Value("${welcome.message:Hello}")
private String message = "Hello World";


@RequestMapping("/")
public String home(Map<String, Object> model) {
model.put("message", this.message);
return "index";
}


}


index.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>index</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />




<link rel="stylesheet/less" th:href="@{/webapp/assets/theme.siberia.less}"/>


<!-- The app's logic -->
<script type="text/javascript" data-main="/webapp/app" th:src="@{/webapp/libs/require.js}"></script>
<script type="text/javascript">
require.config({
paths: { text:"/webapp/libs/text" }
});
</script>






<!-- Development only -->
<script type="text/javascript" th:src="@{/webapp/libs/less.min.js}"></script>




</head>
<body>


</body>
</html>

我有这个确切的问题,然后意识到我在我的application.properties中定义了:

spring.resources.static-locations=file:/var/www/static

这压倒了我所做的一切努力。在我的情况下,我想要两者都保留,所以我只保留了财产,并添加:

spring.resources.static-locations=file:/var/www/static,classpath:static

将src/main/resources/static中的文件作为localhost:{port}/file.html。

以上这些对我来说都没用,因为没有人提到这个可以轻易从网上复制的小属性,以满足不同的目的;)

希望能有所帮助!我想它会很适合这个有这个问题的人的答案的长帖子。

有时候值得检查一下你是否用某个rest控制器重写了全局映射。简单的例子错误(kotlin):

@RestController("/foo")
class TrainingController {


@PostMapping
fun bazz(@RequestBody newBody: CommandDto): CommandDto = return commandDto


}

在上面的例子中,当你请求静态资源时,你会得到:

{
title: "Method Not Allowed",
status: 405,
detail: "Request method 'GET' not supported",
path: "/index.html"
}

原因可能是你想要将@PostMapping映射到/foo,但忘记了@RestController级别上的@RequestMapping注释。在这种情况下,所有请求都被映射到POST,在这种情况下你不会收到静态内容。

只是为一个老问题补充另一个答案……人们已经提到@EnableWebMvc将阻止WebMvcAutoConfiguration加载,这是负责创建静态资源处理程序的代码。还有其他条件也会阻止WebMvcAutoConfiguration加载。要明白这一点,最明确的方法是查看源代码:

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java#L139-L141

在我的例子中,我包含了一个库,它有一个从WebMvcConfigurationSupport扩展的类,这是一个将阻止自动配置的条件:

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

从来没有WebMvcConfigurationSupport扩展是很重要的。相反,从WebMvcConfigurerAdapter扩展。

更新:正确的方法做到这一点在5。实现WebMvcConfigurer

仅供参考:我还注意到,我可以搞砸一个完美工作的春季启动应用程序,并阻止它从静态文件夹的内容,如果我添加一个糟糕的休息控制器这样

 @RestController
public class BadController {
@RequestMapping(method= RequestMethod.POST)
public String someMethod(@RequestParam(value="date", required=false)String dateString, Model model){
return "foo";
}
}

在本例中,在将坏控制器添加到项目后,当浏览器请求静态文件夹中可用的文件时,错误响应为'405方法不允许'。

注意,在坏控制器示例中没有映射路径。

我在spring boot 2.1.3中也遇到了同样的问题,说资源没有找到404。下面我从applicatiion.properties中删除。

#spring.resources.add-mappings=true
#spring.resources.static-locations=classpath:static
#spring.mvc.static-path-pattern=/**,

删除@enableWebMVC和删除任何WebMvcConfigurer覆盖

/ / @EnableWebMvc

还要确保在配置中有@EnableAutoConfiguration

并将所有静态资源放入src / main /资源/静态的,它就像魔术一样最终工作。

静态资源放在以下目录下:

/src/main/resources/static

在应用程序中添加此属性。属性文件

server.servlet.context-path=/pdx

你可以从http://localhost:8080/pdx/images/image.jpg访问

enter image description here

2.使用弹簧启动器。*,我有一个控制器映射到路由GetMapping({"/{var}", "/{var1}/{var2}", "/{var1}/{var2}/{var3}"})和boom我的应用程序停止服务资源。

我知道这样的路线是不可取的,但这完全取决于你正在构建的应用程序(在我的情况下,我别无选择,只能有这样的路线)

所以这里是我的黑客,以确保我的应用程序再次提供资源。我只是有一个映射到资源的控制器。由于spring将在任何有变量的路由之前先匹配直接路由,所以我决定添加一个映射到/imgaes/{name}的控制器方法,并对其他资源重复相同的方法

@GetMapping(value = "/images/{image}", produces = {MediaType.IMAGE_GIF_VALUE, MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE})
public @ResponseBody
byte[] getImage(@PathVariable String image) {
ClassPathResource file = new ClassPathResource("static/images/" + image);
byte[] bytes;
try {
bytes = StreamUtils.copyToByteArray(file.getInputStream());
} catch (IOException e) {
throw new ResourceNotFoundException("file not found: " + image);
}
return bytes;
}

这解决了我的问题

src/main/resources/static下的资源 如果你添加了这段代码,那么src/main/resources/static中的所有静态内容将在"/"下可用:

@Configuration
public class StaticResourcesConfigurer implements WebMvcConfigurer {
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/static/");
}
}

到/**的请求被评估到配置的静态位置 resourceProperties . < / p >

在应用程序上添加以下内容。属性,可能是你唯一需要做的事情…

spring.resources.static-locations=classpath:/myresources/

这将覆盖默认的静态位置,即:

ResourceProperties.CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };

您可能不想这样做,只需确保您的资源最终位于这些默认文件夹中的一个。

执行请求: 如果我将example.html存储在/public/example.html 然后我可以这样访问它:

<host>/<context-path?if you have one>/example.html

如果我想为classpath:/magicofiles/*中的文件提供另一个像<host>/<context-path>/magico/*这样的uri,你需要更多的配置

@Configuration
class MyConfigClass implements WebMvcConfigurer


@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/magico/**").addResourceLocations("/magicofiles/");
}

在我的例子中,一些静态文件没有提供,比如.woff字体和一些图像。但是css和js工作得很好。

更新:让Spring Boot正确地服务于woff字体的一个更好的解决方案是配置回答中提到的资源过滤,例如(注意,你需要同时包含和排除):

<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>static/aui/fonts/**</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>static/aui/fonts/**</include>
</includes>
</resource>
</resources>

-----旧的解决方案(工作,但会破坏一些字体)-----

另一个解决方案是禁用后缀模式匹配setUseSuffixPatternMatch(false)

@Configuration
public class StaticResourceConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
// disable suffix matching to serve .woff, images, etc.
configurer.setUseSuffixPatternMatch(false);
}
}

致谢:@Abhiji确实给了我4分。方向对了!

在我的例子中,我有一个spring引导应用程序,它混合了spring和jaxrs。所以我有一个java类,它继承自类org.glassfish.jersey.server.ResourceConfig。我必须将这一行添加到该类的构造函数中,以便spring端点仍然被称为:property(ServletProperties.FILTER_FORWARD_ON_404, true)

我使用Spring Boot 2.2,没有得到任何静态内容。我发现了两种适合我的方法:

选项#1 -停止使用@EnableWebMvc注释 该注释禁用了一些自动配置,包括自动从常用位置(如/src/main/resources/static)提供静态内容的部分。如果你真的不需要@EnableWebMvc,那么只需从你的@Configuration类中删除它 < p > 选项#2 -在你的__ABC1注释类中实现WebMvcConfigurer并实现addResourceHandlers() 这样做:

@EnableWebMvc
@Configuration
public class SpringMVCConfiguration implements WebMvcConfigurer {


@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
registry.addResourceHandler("/vendor/**").addResourceLocations("classpath:/static/vendor/");
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
}


}

请记住,您的代码现在负责管理所有静态资源路径。

适用于Thymeleaf,可以使用链接样式表

    <link th:href="@{/css/style.css}" rel="stylesheet" />