Spring Boot不提供静态内容

时间:2014-07-09 18:31:23

标签: spring spring-mvc spring-boot

我无法让我的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)

25 个答案:

答案 0 :(得分:142)

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

    您班上的
  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. 如前所述,请求网址将相对解析为这些位置。因此,当请求网址为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);
    }
    
  5. 恕我直言,在代码中减少错误的唯一方法就是尽可能不编写代码。使用已经提供的内容,即使需要进行一些研究,回报也是值得的。

答案 1 :(得分:64)

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

答案 2 :(得分:47)

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

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

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

答案 3 :(得分:22)

寻找映射到" /&#34的控制器;或没有路径映射。

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

答案 4 :(得分:18)

配置可以如下:

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {

// specific project configuration

}

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

此处需要评论的另一件事是,只有在没有&#的情况下,才会注册这些默认资源位置(/static/public/resources/META-INF/resources) 39; t已经将资源处理程序映射到/**

从此刻起,如果您在src/main/resources/static/images上有一个名为image.jpg的图片,您可以使用以下网址访问它:http://localhost:8080/images/image.jpg(在端口8080上启动服务器)并将应用程序部署到根上下文中。)

答案 5 :(得分:11)

您检查了Spring Boot reference docs吗?

  

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

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

答案 6 :(得分: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。

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

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

答案 7 :(得分: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
    }
.....
}

答案 8 :(得分: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扩展。

答案 9 :(得分: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目标)

答案 10 :(得分:2)

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

做上述2件事解决了我的问题。现在我的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>

答案 11 :(得分:1)

使用Spring Boot 2. *,我有一个控制器,该控制器映射到路由GetMapping({"/{var}", "/{var1}/{var2}", "/{var1}/{var2}/{var3}"}),使我的应用停止提供资源。

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

所以这是我的技巧,以确保我的应用再次提供资源。我只是有一个映射到我的资源的控制器。由于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;
    }

这解决了我的问题

答案 12 :(得分: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 中,它最终就像魔术一样工作。

答案 13 :(得分:1)

在目录下放置静态资源

/src/main/resources/static

将此属性添加到application.properties文件中

server.servlet.context-path=/pdx

您可以从http://localhost:8080/pdx/images/image.jpg

访问

enter image description here

答案 14 :(得分:0)

就我而言,没有提供某些静态文件,例如.woff字体和某些图像。但是css和js可以正常工作。

更新:使Spring Boot正确提供woff字体的一种更好的解决方案是配置this答案中提到的资源过滤,例如(请注意,您需要同时包含和排除):

<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确实向我指出了正确的方向!

答案 15 :(得分:0)

我正在使用Spring Boot 2.2,但没有得到任何静态内容。我发现了两种对我有用的解决方案:

选项1-停止使用@EnableWebMvc注释 此注释会禁用一些自动配置,包括自动提供来自/src/main/resources/static等常用位置的静态内容的部分。如果您真的不需要@EnableWebMvc,只需将其从您的@Configuration类中删除。

选项2-在您的WebMvcConfigurer带注释的类中实现@EnableWebMvc并实现 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/");
    }

}

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

答案 16 :(得分:0)

在我的情况下,我有一个Spring Boot应用程序,该应用程序混合了spring和jaxrs。因此,我有一个从类org.glassfish.jersey.server.ResourceConfig继承的Java类。我必须将此行添加到该类的构造函数中,以便弹簧端点仍称为:property(ServletProperties.FILTER_FORWARD_ON_404, true)

答案 17 :(得分:0)

对/ **的请求将评估到在中配置的静态位置 resourceProperties

在application.properties上添加以下内容,可能是您唯一需要做的...

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

如果我想要另一个<host>/<context-path>/magico/*这样的uri用于类路径中的文件:/ magicofiles / *,则需要更多的配置

@Configuration
class MyConfigClass implements WebMvcConfigurer

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

答案 18 :(得分:0)

在src / main / resources / static下提供资源, 如果添加此代码,则src / main / resources / static中的所有静态内容都将在“ /”下显示:

class Program
    {
        static void Main(string[] args)
        {
            X509Certificate2Collection collection;
            using (var store = new X509Store(StoreLocation.LocalMachine))
            {
                store.Open(OpenFlags.ReadOnly);
                collection = store.Certificates;
            }

            var cluster = Cluster.Builder()
                .AddContactPoints("192.168.14.11")
                .WithCredentials("cassandra","cassandra")
                .WithSSL(new SSLOptions().SetCertificateCollection(collection))
                .Build();

            ISession session = cluster.Connect();

            global::System.Console.WriteLine("test");

        }
    }

答案 19 :(得分:0)

仅供参考::我还注意到,如果我像这样添加一个坏的休息控制器,我可以弄乱一个运行良好的spring boot应用程序,并阻止它从静态文件夹中提供内容

 @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 ”。

错误的控制器示例中未映射通知路径。

答案 20 :(得分:0)

我处于同样的情况,即我的spring-boot角度应用程序(集成)不提供静态文件夹内容来在localhost:8080上显示UI。前端是使用angular4开发的,因此使用ng build会在输出路径dir src / main / resources / static中生成文件,但不显示任何内容。我专门为控制器提供了一个服务于index.html的控制器,但似乎无法进行春季引导来了解角度路由选择,而localhost:8080只是在网页上显示了我的控制器方法“ index.html”返回的字符串。 下面是index.html(我将主体中的默认选择器标记更改为,因为登录组件是我创建的登录组件,也是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是否提供了类似的选项来创建源目录/文件夹?我确实从右键菜单->新建->目录创建。但是不确定是否是同一件事,想知道是否会导致我的问题?

答案 21 :(得分: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,在这种情况下您将不会收到静态内容。

答案 22 :(得分:0)

我正在使用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配置开启。

答案 23 :(得分:0)

有同样的问题,使用gradle和eclipse,花了好几个小时试图找出它。

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

答案 24 :(得分:-1)

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

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

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

}