【问题标题】:How to service external static HTML files in Spring Boot Embedded tomcat?如何在 Spring Boot Embedded tomcat 中为外部静态 HTML 文件提供服务?
【发布时间】:2013-12-02 13:47:17
【问题描述】:

我是 Spring 框架和 Spring Boot 的新手。
我已经实现了一个非常简单的 RESTful Spring Boot Web 应用程序。
您可以在另一个问题中看到几乎完整的源代码:Spring Boot: How to externalize JDBC datasource configuration?

app如何服务外部静态HTML、css js文件?
例如,目录结构可能如下:

MyApp\
   MyApp.jar (this is the Spring Boot app that services the static files below)
   static\
       index.htm
       images\
           logo.jpg
       js\
           main.js
           sub.js
       css\
           app.css
       part\
           main.htm
           sub.htm

我已经阅读了构建包含静态 HTML 文件的 .WAR 文件的方法,但由于即使对单个 HTML 文件进行修改,它也需要重新构建和重新部署 WAR 文件,因此该方法是不可接受的。

由于我对 Spring 的了解非常有限,因此最好给出准确而具体的答案。

【问题讨论】:

  • 什么是不工作的? /static 中的类路径资源默认作为静态资源提供(也在 /public 和其他几个地方),因此您应该能够运行您的应用并加载 /css/app.css。
  • @DaveSyer 实际上,当我在 MyApp 目录中运行 MyApp.jar 时,我发现它有效。我在阅读 org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory 的源代码时验证了它。它在 COMMON_DOC_ROOTS 中有“静态”。 (见github.com/spring-projects/spring-boot/blob/master/spring-boot/…)但是我找不到任何关于它的文档,所以我认为在WAR文件中包含静态文件是唯一的方法。
  • @DaveSyer 而且我想将静态文件的目录更改为我想要的任何位置,无论类路径或当前目录如何。我的问题的目录结构只是一个示例(框架意外支持)。于是我又发了一个问题,换个角度来看问题。 (见stackoverflow.com/questions/20069130/…

标签: spring tomcat spring-boot


【解决方案1】:

我从another of your questions 看到,您真正想要的是能够从默认值更改应用程序中静态资源的路径。撇开你为什么要这样做的问题不谈,有几个可能的答案。

  • 一个是您可以提供WebMvcConfigurerAdapter 类型的普通Spring MVC @Bean 并使用addResourceHandlers() 方法向静态资源添加其他路径(默认值请参见WebMvcAutoConfiguration)。
  • 另一种方法是使用ConfigurableEmbeddedServletContainerFactory 功能来设置servlet 上下文根路径。
  • 为此,完整的“核选项”是提供EmbeddedServletContainerFactory 类型的@Bean 定义,以您想要的方式设置servlet 容器。如果您使用现有的具体实现之一,它们会扩展您已经找到的Abstract* 类,因此它们甚至有一个名为documentRoot 的属性的设置器。您还可以使用 EmbeddedServletContainerCustomizer 类型的 @Bean 进行许多常见操作。

【讨论】:

  • 感谢您的回答。所以我在另一个问题中的方法是你的最后一个建议。现在,我会坚持下去(因为它有效)。在研究了更多的 Spring 和 Spring Boot 之后,也许我会改变方法。
  • 我之所以要更改静态文件的默认位置,只是为了开发和部署环境的灵活性。可能我现在对 Spring 框架(甚至 Java)的约定还不够了解。
  • 请注意,对于 spring-boot 2.x,这些类更改了它们的名称。现在是ConfigurableTomcatWebServerFactoryTomcatServletWebServerFactoryTomcatServletWebServerFactoryCustomizer
【解决方案2】:

如果你指定'-cp'就足够了。命令'java -jar blabla.jar'和当前目录中的选项是'static'目录

【讨论】:

  • 我发现这个答案更简单,不需要更改代码。但要使其按预期工作,OP 需要将其 static 文件夹重命名为 public,因为 spring boot(此处为 v1.1.6)将在类路径中查找 public 文件夹。
  • 这个解决方案非常适合前端开发,只需在 IDE 中添加运行时依赖项。然后您可以编辑 html/javascript 内容,而无需重新打包/重新启动后端。
【解决方案3】:

看看this Dave Syer 的答案实现。

您可以使用ConfigurableEmbeddedServletContainer.setDocumentRoot(File documentRoot) 设置Web 上下文将使用的文档根目录来提供静态文件。

工作示例:

package com.example.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.File;
import java.nio.file.Paths;

@Configuration
public class WebConfigurer implements ServletContextInitializer, EmbeddedServletContainerCustomizer {
    private final Logger log = LoggerFactory.getLogger(WebConfigurer.class);

    private final Environment env;
    private static final String STATIC_ASSETS_FOLDER_PARAM = "static-assets-folder";
    private final String staticAssetsFolderPath;

    public WebConfigurer(Environment env, @Value("${" + STATIC_ASSETS_FOLDER_PARAM + ":}") String staticAssetsFolderPath) {
        this.env = env;
        this.staticAssetsFolderPath = staticAssetsFolderPath;
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        if (env.getActiveProfiles().length > 0) {
            log.info("Web application configuration, profiles: {}", (Object[]) env.getActiveProfiles());
        }
        log.info(STATIC_ASSETS_FOLDER_PARAM + ": '{}'", staticAssetsFolderPath);
    }

    private void customizeDocumentRoot(ConfigurableEmbeddedServletContainer container) {
        if (!StringUtils.isEmpty(staticAssetsFolderPath)) {
            File docRoot;
            if (staticAssetsFolderPath.startsWith(File.separator)) {
                docRoot = new File(staticAssetsFolderPath);
            } else {
                final String workPath = Paths.get(".").toUri().normalize().getPath();
                docRoot = new File(workPath + staticAssetsFolderPath);
            }
            if (docRoot.exists() && docRoot.isDirectory()) {
                log.info("Custom location is used for static assets, document root folder: {}",
                        docRoot.getAbsolutePath());
                container.setDocumentRoot(docRoot);
            } else {
                log.warn("Custom document root folder {} doesn't exist, custom location for static assets was not used.",
                        docRoot.getAbsolutePath());
            }
        }
    }

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        customizeDocumentRoot(container);
    }

}

现在您可以使用 command line 和配置文件 (src\main\resources\application-myprofile.yml) 自定义您的应用:

> java -jar demo-0.0.1-SNAPSHOT.jar --static-assets-folder="myfolder"
> java -jar demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=myprofile

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-12
    • 2019-05-31
    • 2021-01-16
    • 1970-01-01
    • 2019-07-11
    • 2017-01-21
    • 2016-12-20
    • 2015-10-30
    相关资源
    最近更新 更多