首页 文章

Spring Boot不提供静态内容

提问于
浏览
122

我现在正撞在墙上几个小时 . 我的项目差不多完成了,但我无法让它服务于静态内容 .

我在 src/main/resources 下放置了一个名为 static 的文件夹 . 在里面我有一个名为 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)

18 回答

  • 18

    我处于相同的情况,我的spring-boot角度应用程序(集成)不提供静态文件夹内容以在localhost:8080上显示UI . 前端是在angular4中开发的,因此使用了 ng build ,它在输出路径dir src / main / resources / static中生成文件,但不显示任何内容 . 我专门为index.html创建了一个控制器,但似乎有些东西是关于spring-boot以了解角度路由的东西和localhost:8080只是在网页上显示我的控制器方法"index.html"返回的字符串 . 下面是index.html(我在body中更改了默认选择器标签,因为登录组件是我创建的那个,我的主要角度组件用于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的项目,而 Spring 季启动版本是 - org.springframework.boot:spring-boot-starter-web:2.0.2.RELEASE .

    @Vizcaino - 正如你所说的那样有一个简单的技巧 - Intellijidea也提供了类似的选项来创建源目录/文件夹吗?我从右键菜单 - >新建 - >目录创建 . 但不确定它是否相同,想知道它是否会导致我的问题?

  • 0

    配置可以如下:

    @Configuration
    @EnableWebMvc
    public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {
    
    // specific project configuration
    
    }
    

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

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

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

  • 4

    有同样的问题,使用gradle和eclipse并花费数小时试图找出它 .

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

  • 21

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

    如果在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 目标)

  • 46

    这个解决方案对我有用:

    首先,在webapp / WEB-INF下放置一个资源文件夹,如下所示

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

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

    然后,您可以访问您的资源内容,例如http://localhost:8080/resource/image/yourimage.jpg

  • 11

    FYI: 我还注意到我可以弄乱一个完美的 spring 启动应用程序并防止它从静态文件夹中提供内容,如果我添加一个糟糕的休息控制器,如此

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

    通知路径未映射到坏控制器示例中 .

  • 0

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

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

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

  • 59

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

    你班上的

    • @EnableWebMvc 将禁用 org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration . 那是_212340的问题 .

    • 除了已经提供的内容之外,无需编写任何代码来为静态资源添加其他位置 . 从v1.3.0.RELEASE查看 org.springframework.boot.autoconfigure.web.ResourceProperties ,我看到一个可以在 application.properties 中配置的字段 staticLocations . 这是来自源代码的片段:

    /**
     * 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;
    
    • 如前所述,请求URL将被解析为 relative 到这些位置 . 因此,当请求URL为 /index.html 时,将提供 src/main/resources/static/index.html . 从Spring 4.1开始,负责解析路径的类是 org.springframework.web.servlet.resource.PathResourceResolver .

    • 默认情况下启用后缀模式匹配,这意味着对于请求URL /index.html ,Spring将查找与 /index.html 对应的处理程序 . 如果打算提供静态内容,这是一个问题 . 要禁用它,请扩展 WebMvcConfigurerAdapter (但不要使用 @EnableWebMvc )并覆盖 configurePathMatch ,如下所示:

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        super.configurePathMatch(configurer);
    
        configurer.setUseSuffixPatternMatch(false);
    }
    

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

  • 0

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

  • 2

    如上所述,该文件应该在 $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.
    }
    ...
    

    }

  • 2

    我认为以前的答案很好地解决了这个问题 . 但是,我要补充一点,在您的应用程序中启用了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
        }
    .....
    }
    
  • 4

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

    做上述两件事解决了我的问题 . 现在我的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>
    
  • 3

    我使用1.3.5并通过Jersey实现托管一堆REST服务 . 这工作正常,直到我决定添加几个HTMLs 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配置开启 .

  • 0

    你看过Spring Boot reference docs了吗?

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

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

  • 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 但忘记 @RestController 级别的 @RequestMapping 注释 . 在这种情况下,所有请求都映射到 POST ,在这种情况下您将不会收到静态内容 .

  • 123

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

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

  • -1

    我遇到了这个问题,然后意识到我已经定义了我的问题application.properties:

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

    这超越了我尝试的其他一切 . 在我的情况下,我想保留两者,所以我保留了 property 并添加:

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

    其中src / main / resources / static提供的文件为localhost: /file.html .

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

    希望能帮助到你!认为它适合这个有问题的人的长期答案 .

相关问题