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

我在src/main/resources下放置了一个名为static的文件夹。其中有一个名为images的文件夹。当我将应用程序打包并运行时,它无法找到我放在该文件夹中的图像。

我试着把静态文件放在公共、资源和META-INF/资源中,但都不起作用。

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

知道为什么弹簧靴找不到这个吗?(我使用1.1.4 BTW)


当前回答

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

以上两件事解决了我的问题。现在我的春季引导加载静态资源没有任何问题。 @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>

其他回答

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

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

在我的情况下,我有“/static/css”,“/static/js”,“/static/images”默认允许,但/static/fonts/**被我的Spring安全实现阻塞。

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

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

中配置的静态位置对/**的请求进行评估 resourceProperties。

在应用程序上添加以下内容。属性,可能是你唯一需要做的事情…

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

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

@Configuration
class MyConfigClass implements WebMvcConfigurer

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

给定src/main/resources/static下的资源, 如果你添加了这段代码,那么src/main/resources/static中的所有静态内容将在"/"下可用:

@Configuration
public class StaticResourcesConfigurer implements WebMvcConfigurer {
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/static/");
    }
}

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

@EnableWebMvc on your class will disable org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration. That's fine if you want complete control but otherwise, it's a problem. 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.ResourceProperties from v1.3.0.RELEASE, I see a field staticLocations that 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; As mentioned before, the request URL will be resolved relative to these locations. Thus src/main/resources/static/index.html will 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. 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 configurePathMatch as shown below: @Override public void configurePathMatch(PathMatchConfigurer configurer) { super.configurePathMatch(configurer); configurer.setUseSuffixPatternMatch(false); }

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

2021年7月编辑:

WebMvcConfigurerAdapter自Spring 5以来已弃用。实现WebMvcConfigurer并使用@Configuration进行注释。