0

アプリケーションで Spark Framework を使用しています。

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

そこにcssおよびjsファイルを含むwebjarを使用できるようにします。src/main/resources/META-INF/resourcesまた、gradle ビルドがそこからリソースを取得するため、プロジェクト フォルダーに独自のリソースを配置しています。

私のビルドでは、すべてが 1 つの jar にまとめられ、すべてのファイルが Spark によって完全に提供される、fat-jar アプローチを使用しています。

私の問題は、いくつかの単体テストを 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 コードをThe thread context class loader will be used for loading the resource.見ると、コード自体が末尾のスラッシュを削除していることもわかります。これにより、プレーンなgetResourceAsStream.

これは Spark のバグですか、それとも正しく動作させる方法はありますか?

4

1 に答える 1

1

Spark ではなく、jetty では先頭のスラッシュを削除する必要があることに注意してください。

残念ながら、Spark では、静的ファイル (物理ディレクトリ/フォルダー内) と、jar 内のリソースとして提供されるファイルを混在させることはできません。また、多くの jar は Spark でも機能しません。

数週間前にこれを調べたところ、これは Spark のマイナーな弱点 (またはバグと言う場合もあります) であるという結論に達しました。

私が見つけた唯一の方法は、Spark を逆にして、jetty がどのように機能するかを理解することでした。次の Nashorn JavaScript スニペットを使用して、webjar と静的ファイルを連携させました。

Spark の作成者が自分のコードを変更して、テーラーメイドのコンテキスト ハンドラーを含めることができるようにしない限り、これは役に立ちません。しかし、代わりに突堤で追求したい場合は、この適応コードが役立ちます。

このコードは Nashorn jjs (JDK8 から) 用ですが、Java に簡単に移植できます。このコードでは、3 つの個別の webjars jquery/bootstrap/angular を使用でき、残りのクライアント コードは物理的な directory/folder にあり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();

}

ソース/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;
})();
于 2015-06-23T08:34:42.223 に答える