如何从 Spring Boot 提供静态 html?

Posted

技术标签:

【中文标题】如何从 Spring Boot 提供静态 html?【英文标题】:How can I serve static html from spring boot? 【发布时间】:2017-07-12 14:29:44 【问题描述】:

我从here 运行 spring-boot-sample-web-static 项目,对 pom 进行了修改

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

并添加了此类以从同一 static 文件夹位置提供重复页面 index2.html

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class Rester 

    @RequestMapping(value = "/rand", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    private RandomObj jsonEndpoint() 
        return new RandomObj();
    

    @RequestMapping(value = "/tw")
    public String somePg() 
        return "index2";
    

json url 工作正常,但是当我尝试访问 localhost:8080/tw 时,我得到一个空白页面,并且控制台中出现此错误:

2017-02-22 15:37:22.076 ERROR 21494 --- [nio-8080-exec-9] o.s.boot.web.support.ErrorPageFilter     : Cannot forward to error page for request [/tw] as the response has already been committed. As a result, the response may have the wrong status code. If your application is running on WebSphere Application Server you may be able to resolve this problem by setting com.ibm.ws.webcontainer.invokeFlushAfterService to false

我做错了吗?

【问题讨论】:

你并不需要依赖tomcat,spring starter web & thymeleaf 应该可以。 thymeloaf 不是必需的。只需将index.html 放入src/main/resources/static/ 文件夹,静态html 就完成了! 【参考方案1】:

静态文件应该从资源中提供,而不是从控制器中提供。

Spring Boot 将自动添加位于其中的静态 Web 资源 以下任一目录:

/META-INF/resources/  
/resources/  
/static/  
/public/

参考:https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boothttps://spring.io/guides/gs/serving-web-content/

【讨论】:

哦,好的,我看到 localhost:8080/index2.html 实际上可以从浏览器中查看,并且无法从控制器中提供它? 检查我的第二个参考链接,或者如果你不想处理参数:***.com/a/27279742/3862022 我要加 spring-boot-starter-thymeleaf 并且只引用模板目录下的文件,我想我明白了,谢谢 谢谢!我创建了文件夹resources/static,放了一个index.html 文件,它就可以工作了! 这些目录应该位于src/main/resourcessrc/main/resources 不会自动提供。【参考方案2】:

在 Spring boot 中,/META-INF/resources//resources/static/public/ 目录可用于提供静态内容。

所以你可以在resources/ 目录下创建一个static/public/ 目录并将你的静态内容放在那里。可以通过以下方式访问它们:http://localhost:8080/your-file.ext。 (假设server.port 是 8080)

您可以使用application.properties 中的spring.resources.static-locations 自定义这些目录。

例如:

spring.resources.static-locations=classpath:/custom/

现在您可以使用resources/ 下的custom/ 文件夹来提供静态文件。

这也可以在 Spring Boot 2 中使用 Java 配置:

@Configuration
public class StaticConfig implements WebMvcConfigurer 

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/custom/");
    

此配置将custom 目录的内容映射到http://localhost:8080/static/** url。

【讨论】:

【参考方案3】:

我正在使用:: Spring Boot :: (v2.0.4.RELEASE) with Spring Framework 5

Spring Boot 2.0 需要 Java 8 作为最低版本。许多现有 API 已更新以利用 Java 8 功能,例如:接口上的默认方法、函数回调和新 API,如 javax.time。

静态内容

默认情况下,Spring Boot 从名为 /static(或 /public/resources/ 的目录中提供静态内容META-INF/resources) 在类路径中或从 ServletContext 的根目录中。它使用 Spring MVC 中的 ResourceHttpRequestHandler,因此您可以通过添加自己的 WebMvcConfigurer 并覆盖 addResourceHandlers 方法来修改该行为。

默认情况下,资源映射到/** 并位于/static 目录中。 但是您可以在我们的 Web 上下文配置类中以编程方式自定义静态位置。

@Configuration @EnableWebMvc
public class Static_ResourceHandler implements WebMvcConfigurer 

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        // When overriding default behavior, you need to add default(/) as well as added static paths(/webapp).

        // src/main/resources/static/...
        registry
            //.addResourceHandler("/**") // « /css/myStatic.css
            .addResourceHandler("/static/**") // « /static/css/myStatic.css
            .addResourceLocations("classpath:/static/") // Default Static Loaction
            .setCachePeriod( 3600 )
            .resourceChain(true) // 4.1
            .addResolver(new GzipResourceResolver()) // 4.1
            .addResolver(new PathResourceResolver()); //4.1

        // src/main/resources/templates/static/...
        registry
            .addResourceHandler("/templates/**") // « /templates/style.css
            .addResourceLocations("classpath:/templates/static/");

        // Do not use the src/main/webapp/... directory if your application is packaged as a jar.
        registry
            .addResourceHandler("/webapp/**") // « /webapp/css/style.css
            .addResourceLocations("/");

        // File located on disk
        registry
            .addResourceHandler("/system/files/**")
            .addResourceLocations("file:///D:/");
    

http://localhost:8080/handlerPath/resource-path+name
                    /static         /css/myStatic.css
                    /webapp         /css/style.css
                    /templates      /style.css

在 Spring 中,每个请求都将通过 DispatcherServlet。为了避免通过 DispatcherServlet(Front contoller) 请求静态文件,我们配置 MVC Static content。

正如@STEEL所说,静态资源不应该通过Controller。 Thymleaf 是一个 ViewResolver,它采用视图名称表单控制器并将 prefixsuffix 添加到视图层。

【讨论】:

【参考方案4】:

如前所述,某些文件夹(/META-INF/resources/、/resources/、/static/、/public/)默认提供静态内容,控制器配置错误可能会破坏此行为。

人们在 @RestController 注释中定义控制器的基本 url,而不是控制器顶部的 @RequestMapping 注释,这是一个常见的陷阱。

这是错误的:

@RestController("/api/base")
public class MyController 

    @PostMapping
    public String myPostMethod( ...) 

以上示例将阻止您打开 index.html。 Spring 期望根有一个 POST 方法,因为 myPostMethod 映射到“/”路径。

你必须改用这个:

@RestController
@RequestMapping("/api/base")
public class MyController 

    @PostMapping
    public String myPostMethod( ...) 

【讨论】:

【参考方案5】:

我不得不向 pom.xml 添加 thymeleaf 依赖项。没有这个依赖,Spring boot 找不到静态资源。

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

【讨论】:

【参考方案6】:

您可以通过thymeleaf(参考:source)在 JAVA Spring-boot App 中快速提供静态内容

我假设你已经添加了 Spring Boot 插件apply plugin: 'org.springframework.boot' 和必要的buildscript

然后继续添加 thymeleaf 到您的build.gradle ==>

dependencies 
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    testCompile('org.springframework.boot:spring-boot-starter-test')

假设您在 src/main/resources 添加了 home.html 要提供此文件,您需要创建一个控制器。

package com.ajinkya.th.controller;

  import org.springframework.stereotype.Controller;
  import org.springframework.web.bind.annotation.RequestMapping;

  @Controller
  public class HomePageController 

      @RequestMapping("/")
      public String homePage() 
        return "home";
      

  

就是这样!现在重新启动您的 gradle 服务器。 ./gradlew bootRun

【讨论】:

以上是关于如何从 Spring Boot 提供静态 html?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Boot 从不同端口提供 REST API 和静态内容

Spring Boot - 如何为指定根目录中的多个路由提供一个静态 html 文件

如何使用 jar 外部的 spring boot 提供静态内容?

在配置中定义servlet路径时如何在spring boot中提供静态内容

如何利用spring boot做一个简单的web应用

Spring Boot不提供静态内容