Spring Boot不提供静态内容

问题描述 投票:135回答:19

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

我在static下放了一个名为src/main/resources的文件夹。在里面我有一个名为images的文件夹。当我打包应用程序并运行它时,它找不到我放在该文件夹上的图像。

我试图把静态文件放在publicresourcesMETA-INF/resources但没有任何作用。

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

有什么想法为什么spring-boot没有找到这个? (我使用的是1.1.4 BTW)

spring spring-mvc spring-boot
19个回答
149
投票

一年多以后没有提高死亡人数,但所有以前的答案都错过了一些关键点:

  1. 你班上的@EnableWebMvc将禁用org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration。如果您想要完全控制,那就没关系,否则,这是一个问题。
  2. 除了已经提供的内容之外,无需编写任何代码来为静态资源添加其他位置。从v1.3.0.RELEASE看org.springframework.boot.autoconfigure.web.ResourceProperties,我看到可以在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为src/main/resources/static/index.html时,将提供/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); }

恕我直言,在代码中减少错误的唯一方法是尽可能不编写代码。使用已经提供的内容,即使需要进行一些研究,回报也是值得的。


3
投票

只是为一个旧问题添加另一个答案......人们已经提到@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延伸。


2
投票

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

如果您使用的是Maven,请执行:

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

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


2
投票

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

做上述两件事解决了我的问题。现在我的spring boot正在加载静态资源,没有任何问题。 @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>

1
投票

我使用1.3.5并通过Jersey实现托管一堆REST服务。这很好,直到我决定添加几个HTML + js文件。在这个论坛上给出的答案都没有帮助我。但是,当我在我的pom.xml中添加了以下依赖项时,src / main / resources / static中的所有内容终于通过浏览器显示:

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

似乎spring-web / spring-webmvc是重要的传递依赖,它使spring boot auto配置打开。


1
投票

仅供参考:我也注意到我可以弄乱一个完美的弹簧启动应用程序,并防止它从静态文件夹中提供内容,如果我添加一个坏的休息控制器,如此

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

在此示例中,在将坏控制器添加到项目后,当浏览器要求在静态文件夹中提供文件时,错误响应为“405 Method Not Allowed”。

注意路径未映射到坏控制器示例中。


1
投票

我在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 / resources / static中,它最终就像魔术一样......


0
投票

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

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


0
投票

好吧有时值得检查你是否覆盖了一些休息控制器的全局映射。简单的例子错误(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但忘记@RequestMapping级别上的@RestController注释。在这种情况下,所有请求都映射到POST,在这种情况下您将不会收到静态内容。


0
投票

我处于相同的情况,我的spring-boot角度应用程序(集成)不提供静态文件夹内容以在localhost:8080上显示UI。前端是在angular4中开发的,所以使用ng build在输出路径dir src / main / resources / static中生成文件,但不显示任何内容。我专门为index.html提供了一个控制器,但似乎有些东西是关于spring-boot以了解角度路由的东西和localhost:8080只是在网页上显示我的控制器方法“index.html”返回的字符串。下面是index.html(我在body中更改了默认选择器标签,因为登录组件是我创建的那个,我的主要角度组件用于UI但是仍然无法运行app-root还是这个):

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Hello Test App</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-login></app-login>
<script type="text/javascript" src="runtime.js"></script><script type="text/javascript" src="polyfills.js"></script><script type="text/javascript" src="styles.js"></script><script type="text/javascript" src="vendor.js"></script><script type="text/javascript" src="main.js"></script></body>
</html>

控制器代码:

@RequestMapping("/")
public String userInterface() {
    return "index.html";
}

不确定它是否重要,但这是在IntellijIdea开发的基于gradle的项目,春季启动版本是-org.springframework.boot:spring-boot-starter-web:2.0.2.RELEASE

@Vizcaino - 正如你所说,有一个简单的技巧 - Intellijidea提供了类似的选项来创建源目录/文件夹吗?我从右键菜单 - >新建 - >目录创建。但不确定它是否相同,想知道它是否会导致我的问题?


-1
投票

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

如果您的文件不在标准目录中,则可以添加以下配置:

@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.
}
...

}


66
投票

与spring-boot状态不同,为了让我的spring-boot jar服务于内容:我必须通过这个配置类专门添加注册我的src / main / resources / static内容:

@Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {

    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);
    }
}

47
投票

我有一个类似的问题,事实证明,简单的解决方案是让我的配置类扩展WebMvcAutoConfiguration

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

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


22
投票

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

我遇到了这样一个问题,得到了405个错误,并且在几天内困扰我的脑袋。问题原来是一个@RestController注释控制器,我忘了用@RequestMapping注释注释。我猜这个映射路径默认为“/”并阻止静态内容资源映射。


18
投票

配置可以如下:

@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上启动,应用程序部署到根上下文)。


11
投票

你检查了Spring Boot reference docs吗?

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

您还可以将您的项目与指南Serving Web Content with Spring MVC进行比较,或查看spring-boot-sample-web-ui项目的源代码。


6
投票

我遇到了这个问题,然后意识到我已经在我的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。

以上都没有为我工作,因为没有人提到这个可以很容易从网上复制以用于不同目的的小财产;)

希望能帮助到你!想象一下,对于有这个问题的人来说,它很适合这篇长篇文章。


5
投票

我认为之前的答案很好地解决了这个问题。但是,我要补充说,在一种情况下,当你在应用程序中启用Spring Security时,你可能必须明确告诉Spring允许对其他静态资源目录的请求,例如“/ static / fonts”。

在我的情况下,默认情况下我有“/ static / css”,“/ static / js”,“/ static / images”,但我的Spring Security实现阻止了/ static / fonts / **。

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

@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
    }
.....
}

3
投票

这个解决方案对我有用:

首先,在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

© www.soinside.com 2019 - 2024. All rights reserved.