Spring Boot 不提供静态内容

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24661289/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 06:49:13  来源:igfitidea点击:

Spring Boot not serving static content

springspring-mvcspring-boot

提问by Vinicius Carvalho

I can't get my Spring-boot project to serve static content.

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

I've placed a folder named staticunder src/main/resources. Inside it I have a folder named images. When I package the app and run it, it can't find the images I have put on that folder.

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

I've tried to put the static files in public, resourcesand META-INF/resourcesbut nothing works.

我试图把静态文件中publicresourcesMETA-INF/resources但没有任何工程。

If I jar -tvf app.jar I can see that the files are inside the jar on the right folder: /static/images/head.pngfor example, but calling: http://localhost:8080/images/head.png, all I get is a 404

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

Any ideas why spring-boot is not finding this? (I'm using 1.1.4 BTW)

为什么 spring-boot 没有找到这个的任何想法?(我正在使用 1.1.4 顺便说一句)

回答by Abhijit Sarkar

Not to raise the dead after more than a year, but all the previous answers miss some crucial points:

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

  1. @EnableWebMvcon your class will disable org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration. That's fine if you want complete control but otherwise, it's a problem.
  2. There's no need to write any code to add another location for static resources in addition to what is already provided. Looking at org.springframework.boot.autoconfigure.web.ResourcePropertiesfrom v1.3.0.RELEASE, I see a field staticLocationsthat can be configured in the application.properties. Here's a snippet from the source:

    /**
     * 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. As mentioned before, the request URL will be resolved relativeto these locations. Thus src/main/resources/static/index.htmlwill be served when the request URL is /index.html. The class that is responsible for resolving the path, as of Spring 4.1, is org.springframework.web.servlet.resource.PathResourceResolver.

  4. Suffix pattern matching is enabled by default which means for a request URL /index.html, Spring is going to look for handlers corresponding to /index.html. This is an issue if the intention is to serve static content. To disable that, extend WebMvcConfigurerAdapter(but don't use @EnableWebMvc) and override configurePathMatchas shown below:

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        super.configurePathMatch(configurer);
    
        configurer.setUseSuffixPatternMatch(false);
    }
    
  1. @EnableWebMvc在你的课上将禁用org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration. 如果您想要完全控制,那很好,否则,这是一个问题。
  2. 除了已经提供的位置之外,无需编写任何代码来为静态资源添加另一个位置。看着org.springframework.boot.autoconfigure.web.ResourceProperties从v1.3.0.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 将对于这些位置进行解析。因此src/main/resources/static/index.html将在请求 URL 为 时提供服务/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);
    }
    

IMHO, the only way to have fewer bugs in your code is not to write code whenever possible. Use what is already provided, even if that takes some research, the return is worth it.

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

回答by Francois

Unlike what the spring-boot states, to get my spring-boot jar to serve the content: I had to add specifically register my src/main/resources/static content through this config class:

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

回答by Software Engineer

I had a similar problem, and it turned out that the simple solution was to have my configuration class extend WebMvcAutoConfiguration:

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

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

I didn't need any other code to allow my static content to be served, however, I did put a directory called publicunder src/main/webappand configured maven to point to src/main/webappas a resource directory. This means that publicis copied into target/classes, and is therefore on the classpath at runtime for spring-boot/tomcat to find.

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

回答by Johannes

Look for Controllers mapped to "/" or with no path mapped.

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

I had a problem like this, getting 405 errors, and banged my head hard for days. The problem turned out to be a @RestControllerannotated controller that I had forgot to annotate with a @RequestMappingannotation. I guess this mapped path defaulted to "/" and blocked the static content resource mapping.

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

回答by Francisco Spaeth

The configuration could be made as follows:

可以进行如下配置:

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {

// specific project configuration

}

Important here is that your WebMvcConfigmayoverride addResourceHandlersmethod and therefore you need to explicitly invoke super.addResourceHandlers(registry)(it is true that if you are satisfied with the default resource locations you don't need to override any method).

这里重要的是您WebMvcConfig可能会覆盖addResourceHandlers方法,因此您需要显式调用super.addResourceHandlers(registry)(确实,如果您对默认资源位置感到满意,则不需要覆盖任何方法)。

Another thing that needs to be commented here is that those default resource locations (/static, /public, /resourcesand /META-INF/resources) will be registered only if there isn't already a resource handler mapped to /**.

需要在这里评论的另一件事是,那些默认的资源位置(/static/public/resources/META-INF/resources)将只如果有尚未映射到一个资源处理程序注册/**

From this moment on, if you have an image on src/main/resources/static/imagesnamed image.jpgfor instance, you can access it using the following URL: http://localhost:8080/images/image.jpg(being the server started on port 8080 and application deployed to root context).

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

回答by matsev

Did you check the Spring Boot reference docs?

您是否检查过Spring Boot 参考文档

By default Spring Boot will serve static content from a folder called /static(or /publicor /resourcesor /META-INF/resources) in the classpath or from the root of the ServletContext.

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

You can also compare your project with the guide Serving Web Content with Spring MVC, or check out the source code of the spring-boot-sample-web-uiproject.

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

回答by S. Jacob Powell

I was having this exact problem, then realized that I had defined in my application.properties:

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

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

Which was overriding everything else I had tried. In my case, I wanted to keep both, so I just kept the property and added:

这覆盖了我尝试过的所有其他内容。就我而言,我想保留两者,所以我只保留了财产并补充说:

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

Which served files from src/main/resources/static as localhost:{port}/file.html.

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

None of the above worked for me because nobody mentioned this little property that could have easily been copied from online to serve a different purpose ;)

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

Hope it helps! Figured it would fit well in this long post of answers for people with this problem.

希望能帮助到你!认为它非常适合有此问题的人的这篇长篇答案。

回答by Bal

Just to add yet another answer to an old question... People have mentioned the @EnableWebMvcwill prevent WebMvcAutoConfigurationfrom loading, which is the code responsible for creating the static resource handlers. There are other conditions that will prevent WebMvcAutoConfigurationfrom loading as well. Clearest way to see this is to look at the source:

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

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

In my case, I was including a library that had a class that was extending from WebMvcConfigurationSupportwhich is a condition that will prevent the autoconfiguration:

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

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

It's important to neverextend from WebMvcConfigurationSupport. Instead, extend from WebMvcConfigurerAdapter.

重要的是要永远从延长WebMvcConfigurationSupport。相反,从WebMvcConfigurerAdapter.

UPDATE: The proper way to do this in 5.x is to implement WebMvcConfigurer

更新:在 5.x 中执行此操作的正确方法是实现 WebMvcConfigurer

回答by RemusS

I think the previous answers address the topic very well. However, I'd add that in one case when you have Spring Security enabled in your application, you might have to specifically tell Spring to permit requests to other static resource directories like for example "/static/fonts".

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

In my case I had "/static/css", "/static/js", "/static/images" permited by default , but /static/fonts/** was blocked by my Spring Security implementation.

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

Below is an example of how I fixed this.

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

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

回答by ldeng

This solution works for me:

这个解决方案对我有用:

First, put a resources folder under webapp/WEB-INF, as follow structure

首先在webapp/WEB-INF下放置一个resources文件夹,结构如下

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

Second, in spring config file

二、在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/");
    }
}

Then, you can access your resource content, such as http://localhost:8080/resource/image/yourimage.jpg

然后就可以访问你的资源内容了,比如 http://localhost:8080/resource/image/yourimage.jpg