Spring Boot 应用程序无法提供静态内容

10

我正在使用Spring Boot,并尝试在部署后使我的静态资源(CSS,JS,字体)可用。你可以查看或从https://github.com/joecracko/StaticResourceError克隆源代码。

目前,我的CSS、JS和字体文件对于我的部署网站来说是不可见的。

这是我的项目目录结构:

这是我的项目目录结构

这是编译后JAR的根目录:我向您保证,文件存在于它们各自的文件夹中。

输入图像描述

这是我遇到的网络错误:

输入图像描述

这是由Chrome工具提供的我的源代码。请注意,bar.css在此处为空。您可以查看我的源代码以查看它不为空。

输入图像描述

这是我的homepage.html:

<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>

<!-- Main Styles -->
<link rel="stylesheet" href="/css/bar.css" />
<script src="/js/foo.js"></script>

</head>
<body>
    <div>Welcome to Foo!</div>
</body>
</html>

这是我的Web应用程序初始化程序(FooWebAppInitializer.java)

public class FooWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {

        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(ServletConfig.class);

        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));

        //Spring Security
        container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
            .addMappingForUrlPatterns(null, false, "/*");

        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcherServlet", new DispatcherServlet(rootContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/*");
        dispatcher.addMapping("*.css");
        dispatcher.addMapping("*.eot");
        dispatcher.addMapping("*.svg");
        dispatcher.addMapping("*.ttf");
        dispatcher.addMapping("*.woff");
        dispatcher.addMapping("*.map");
        dispatcher.addMapping("*.js");
        dispatcher.addMapping("*.ico");
    }
}

这是我的Servlet配置(ServletConfig.java)

@Configuration
@EnableWebMvc
@ComponentScan({"com.foo"})
public class ServletConfig extends WebMvcAutoConfiguration{

    @Bean
    MultipartResolver multipartResolver() {
        return new StandardServletMultipartResolver();
    }

    @Bean
    public ResourceBundleMessageSource messageSource() {
        ResourceBundleMessageSource source = new ResourceBundleMessageSource();
        source.setBasename("messages");
        return source;
    }
}

仅供参考,这是我的Spring Security配置(WebSecurityConfig.java)。

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().permitAll();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**"); // #3
    }
}
2个回答

19

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

/src/main/resources/static
您还可以将文件夹名称更改为publicresources,而不是static

Explanation: 您的构建工具(如Maven或Gradle)将复制应用程序类路径中/src/main/resources/下的所有内容,并且正如在Spring Boot文档中所述,来自类路径中名为/static(或/public/resources)的目录中的所有内容都将作为静态内容提供。


这个目录也可以使用,但不建议使用:

/src/main/webapp/

如果你的应用程序将被打包为jar文件,请不要使用src/main/webapp目录。尽管这个目录是一个常见的标准,但它只适用于war包,并且如果你生成一个jar文件,大多数构建工具会默默地忽略它。


Spring Boot的文档指出,这不是JAR构建的最佳选择。http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-spring-mvc-static-content - John Douglas George
这两个答案都不好。你可能会遇到实时刷新的问题。最好的方法是遵循Spring Boot文档,在根项目文件夹下的/static目录中包含资源(而不是在src/main/resources文件夹中)。然后,在Chrome中进行更改,保存在Chrome工作区中,并可以看到实时更新而无需重新启动。此外,如果您将其部署为jar时,Maven不会在/static文件夹中获取资源,因此要解决这个问题,您需要阅读/questions/27566967/no-mapping-found-for-http-request-with-uri-web-inf-pages-mainpage-jsp-in-disp/27567879#27567879。 - John Deverall
@JohnDeverall 感谢您指出可能存在的问题。我可以理解实时刷新的问题,这里有一些解决方案。您指出的另一个问题似乎与将内容放在/src/main/webapp并将应用程序打包为jar有关,但是该文件夹在答案中被不鼓励使用。因此,在/src/main/resources/static上保持,除了实时刷新之外,我们还可能遇到其他问题吗? - Andrea
@Andrea 我提到的另一个问题与Maven惯例优先配置方法有关。/static不遵循Maven惯例,因此在/static中的任何内容都不会自动包含在构建产物中。您需要像在另一个问题中那样配置maven,只是用<directory> static </ directory>替换<directory> src / main / webapp </ directory>。如果您选择/src/main/resources/static而不仅仅是static,则我不知道除了实时刷新之外还会遇到其他问题。 - John Deverall
@JohnDeverall 如果 webapp Jar 构件是由 spring-boot-maven-plugin 生成的,那么这将起作用。 - V.Vidyasagar
显示剩余3条评论

3
有两件事情需要考虑(Spring Boot v1.5.2.RELEASE): 1)检查所有Controller类是否有@EnableWebMvc注解,如果有,请删除它。 2)检查使用的控制器类的注解 - @RestController或@Controller。不要在一个类中混合使用Rest API和MVC行为。对于MVC,请使用@Controller,对于REST API,请使用@RestController。
执行以上两个步骤解决了我的问题。现在我的Spring Boot可以无问题地加载静态资源。 @Controller => 加载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>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>

在我的情况下,一切总体上都很好,但是没有任何子路径的请求(即 GET http://localhost:8080)会返回 404 而不是 index.html 文件。删除 @EnableWebMvc 注释可以解决这个问题。 - Iorweth333
谢谢!这帮助我解决了使用自定义json/yml文件而不是生成的文件的问题。一个控制器有@EnableWebMvc,它阻止了swagger-ui的加载。 - jhenya-d

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接