java - Spark 无法从 webjar 加载静态文件

标签 java classloader spark-java

我在我的应用程序中使用 Spark Framework,并使用

staticFileLocation("/META-INF/resources/");

这样我就可以使用 webjar,其中包含 css 和 js 文件。我还将自己的资源放入项目 src/main/resources/META-INF/resources 文件夹中,因为我的 gradle 构建会从那里获取它们。

我的构建使用 fat-jar 方法,所有内容最终都在一个 jar 中,并且所有文件都由 Spark 完美提供服务。

我的问题是,当我从 Eclipse 独立运行一些单元测试时,即使我确保 webjar 位于类路径上,它们也不会由 Spark 提供服务,只有我自己的项目静态资源提供服务。

@Test
public void testStartup() throws InterruptedException {
    InputStream schemaIS = this.getClass().getClassLoader().getResourceAsStream("META-INF/resources/webjars/bootstrap/3.2.0/js/bootstrap.min.js");
    System.out.println(schemaIS == null);
    staticFileLocation("/META-INF/resources/");
    // depending on the trailing / the bootstrap js is found, but Spark never serves it
}

我认为这与类加载器有关,但我没有找到使其工作的方法。查看 Spark 代码,它显示 线程上下文类加载器将用于加载资源。 我还看到代码本身删除了尾部斜杠,这在普通的 getResourceAsStream 中产生了很大的差异.

这是 Spark 中的一个错误吗?或者有什么方法可以使其正常工作吗?

最佳答案

请注意 jetty 需要删除前导斜杠,而不是 Spark。

不幸的是,对于 Spark,您无法将静态文件(在物理目录/文件夹中)与作为 jar 中的资源的文件混合。许多 jar 包在 Spark 中也无法工作。

我几周前看过这个,并得出结论,这是 Spark 的一个小弱点(或者如果你可以说是一个错误)。

我发现的唯一方法是逆向 Spark 并弄清楚 jetty 是如何工作的。我使用以下 Nashorn javascript 片段来使 webjar 和静态文件协同工作。

除非 Spark 作者更改他的代码以允许包含定制的上下文处理程序,否则这对您没有帮助。但如果你想在jetty中进行操作,这段经过适配的代码可以帮助你。

此代码适用于 Nashorn jjs(来自 JDK8),但可以轻松移植到 Java。通过此代码,我可以使用 3 个独立的 webjar jquery/bootstrap/angular,其余的客户端代码位于物理目录/文件夹 public 中。

app.js:

with(new JavaImporter(
  org.eclipse.jetty.server
, org.eclipse.jetty.server.handler
)) {

  var server = new Server(4567);

  var ctxs = new ContextHandlerCollection();
  ctxs.setHandlers(Java.to([
    load('src/static.js')
  , load('src/webjars.js')
  ], Handler.class.getName().concat('[]')));
  server.setHandler(ctxs);

  server.start();
  server.join();

}

src/static.js:

(function () {
  var context;
  with(new JavaImporter(
    org.eclipse.jetty.server.handler
  , org.eclipse.jetty.util.resource
  )) {
    context = new ContextHandler();
    context.setContextPath("/");
    var handler = new ResourceHandler();
    handler.setBaseResource(Resource.newResource("public"));
    context.setHandler(handler);
  }
  return context;
})();

src/webjars.js:

(function () {
  var context;
  with(new JavaImporter(
    org.eclipse.jetty.server.handler
  , org.eclipse.jetty.util.resource
  )) {
    context = new ContextHandler();
    context.setContextPath("/");
    var handler = new (Java.extend(ResourceHandler, {
      getResource: function(req) {
        var path = req.getUri();
        var resource = Resource.newClassPathResource(path);
        if (resource == null || !resource.exists()) {
          resource = Resource.newClassPathResource("META-INF/resources/webjars" + path);
        }
        return resource;
      }
    }))();
    handler.setDirectoriesListed(true); // true when debugging, false in production
    context.setHandler(handler);
  }
  return context;
})();

关于java - Spark 无法从 webjar 加载静态文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30969091/

相关文章:

java - 星火Java : Unable to process parts as no multi-part configuration has been provided

java - 如何在 AWS Elastic Beanstalk 上安装/运行 Spark Java 框架?

java - 将默认值设为先前选择的值 (JSTL)

java - 如何安全地访问 Java 9+ 中类路径中所有资源文件的 URL?

java - Spark 在过滤器之前运行两次

android - 如何访问类加载器/App Linearalloc 类信息大小?

java - 从给定路径加载类

java - 安排Android服务在手机重启后重新启动

java - Android:java.lang.IllegalArgumentException:错误对话线程 ID:15555215554

java - 如何: Organize Buttons and stuff with JavaFX