带有静态内容的Spring Boot项目在运行jar时会生成404

时间:2014-01-26 01:14:02

标签: spring maven jetty spring-boot static-content

Spring最近关于在Spring Boot项目中使用静态Web内容的博客文章(https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot)表明可以使用多个资源目录:

  • / META-INF /资源/
  • /资源/
  • /静态/
  • /公共/

这要归功于WebMvcAutoConfiguration类,它自动将这些目录添加到类路径中。这一切看起来都很好,并且在使用 spring-boot-maven-plugin spring-boot:run 目标时显得正常工作,所有静态内容有效(例如:/index.html)。

当您打包Spring Boot项目并允许 spring-boot-maven-plugin 创建增强型JAR,然后尝试使用java -jar my-spring-boot-project.jar运行项目时,您会发现您的静态内容现在返回404错误。

8 个答案:

答案 0 :(得分:37)

事实证明,虽然Spring Boot在将各种资源目录添加到类路径时非常聪明,但是Maven并不是,而是由你来处理那部分。默认情况下,只有src/main/resources会包含在您的JAR中。如果您在项目的根目录中创建一个名为/static的文件夹(如博客文章所暗示的那样),那么在使用 spring-boot:run Maven的目标,但是一旦你创建了JAR就没有了。

最简单的解决方案是在/static内创建/src/main/resources文件夹,然后Maven将其包含在JAR中。您可以选择将其他资源位置添加到Maven项目中:

<resources>
    <resource>
        <directory>src/main/resources</directory>
    </resource>
    <resource>
        <directory>static</directory>
        <targetPath>static</targetPath>
    </resource>
</resources>

我希望这对某些人有用,当你退后一步看看Maven是如何工作的时候会很明显,但它可能会让一些人使用Spring Boot,因为它的设计非常免配置。

答案 1 :(得分:7)

我正在撞墙,试图弄清楚如何用gradle做到这一点。有什么提示吗?

编辑:我通过将它添加到我的build.gradle中来实现它:

// Copy resources into the jar as static content, where Spring expects it.
jar.into('static') {
    from('src/main/webapp')
}

答案 2 :(得分:3)

我想了解如何在Spring启动环境中提供静态内容。大多数建议都是将静态文件放在/ static / resources / src / main / webapp等中。考虑分享下面的方法。

  1. 允许spring boot自动配置Dispatcher Servlet - 确保DispatcherServletAutoConfiguration不在自动配置的排除中。

    @EnableAutoConfiguration(exclude =         {                 //DispatcherServletAutoConfiguration.class,         })

  2. 为静态内容路由注入外部目录

    @Value( “$ {静态content.locations:文件:C:/ myprj /静态/”) private String [] staticContentLocations;

  3. 3.使用WebMvcConfigurerAdapter取消WebMvcAutoConfiguration建议不使用默认资源位置但使用我们指示的内容。如下所示

    @Bean
        public WebMvcConfigurerAdapter webMvcConfigurerAdapter()
        {
            return new WebMvcConfigurerAdapter()
            {
                @Override
                public void addResourceHandlers(ResourceHandlerRegistry registry)
                {
                    if (!registry.hasMappingForPattern("/**"))
                    {
                        // if this is executed spring won't add default resource
                        // locations - add them to the staticContentLocations if
                        // you want to keep them
                        // default locations:
                        // WebMvcAutoConfiguration.RESOURCE_LOCATIONS
                        registry.addResourceHandler("/**").addResourceLocations(
                                staticContentLocations);
                    }
                }
            };
        }
    

    如果C:/ myprj / static有index.html,则http://localhost:portno/index.html应该有效。希望有所帮助。

答案 3 :(得分:2)

有两件事需要考虑(Spring Boot v1.5.2.RELEASE) -

1)检查@EnableWebMvc注释的所有Controller类,删除  如果有任何

2)检查使用注释的Controller类 -  @RestController或@Controller。

不要在一个类中混合使用Rest API和MVC行为。对于MVC,使用@Controller和REST API使用@RestController

Doing above 2 things resolved my issue. Now my spring boot is loading static resources with out any issues.
@Controller => load index.html => loads static files.

@Controller
public class WelcomeController {

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

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

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

}

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</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>

答案 4 :(得分:2)

Spring Boot将使用WebMvcAutoConfiguration来配置静态内容,该类仅在没有自定义WebMvcConfigurationSupport bean的情况下才会生效,在我的情况下,我确实有一个。

>
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
        WebMvcConfigurerAdapter.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
        ValidationAutoConfiguration.class })
    public class WebMvcAutoConfiguration {

}

所以我只需要自己配置它,这是我的解决方案:

@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/static-file/**").addResourceLocations("classpath:/static/");
}

答案 5 :(得分:0)

我在静态目录中有一个资产文件夹,并在SpringConfig中允许扩展了WebSecurityConfigurerAdapter

http.authorizeRequests().antMatchers("/", "/login", "/assets/**")
            .permitAll()

答案 6 :(得分:0)

当我尝试从现有的工作解决方案中创建一个沙盒示例作为模板(https://github.com/fluentcodes/sandbox/tree/java-spring-boot)时,我偶然发现了这个404主题:未提供静态内容index.html。

由于该示例非常简单且现有解决方案有效,因此我不会深入介绍所提到的深入挖掘弹簧解决方案。

我查看了创建的目标类,没有期望的static / index.html。

原因很简单:我在 src / main / 下而不是在 src / 下创建了资源。由于提到了许多复杂的解决方案,因此需要一些时间来查找。对我来说,这是一个不重要的原因。

另一方面,当启动spring boot时:为什么我没有得到任何提示,所以找不到location1,location2 .... locationx中的静态内容。认为它是一个主题。

答案 7 :(得分:0)

我不得不将thymeleaf依赖项添加到pom.xml。 没有这种依赖性,Spring Boot找不到静态资源。

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