2015-06-21 51 views
0

我使用的Spark框架在我的应用程序加载静态文件,并使用星火不能从webjars

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

,这样我可以用webjars,其中包含有CSS和JS文件。我也有我自己的资源放在我的项目src/main/resources/META-INF/resources文件夹中,因为我的gradle build会从那里拿起它们。

我的版本使用了fat-jar方法,其中一切都以单个jar结尾,所有文件都由Spark完美地提供。

我的问题是,当我从Eclipse单独运行某些单元测试时,即使我确保webjars在类路径上,但它们不是由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 
} 

我认为这与类加载器有关,但我没有找到使这项工作的方法。看看星火代码,它说The thread context class loader will be used for loading the resource.我也看到代码本身删除了尾部的斜杠,这使得在普通的getResourceAsStream中有很大的区别。

这是Spark中的一个错误,还是有什么办法可以使它正常工作?

回答

1

注意删除主要斜杠是由码头需要而不是由Spark。

不幸的是,Spark不能将静态文件(在物理目录/文件夹中)与作为资源的文件混合在jar中。许多罐子在Spark里都不行。

几周前我看了一遍,得出了一个结论,这是Spark的一个小弱点(或者如果你可能会说的话,是一个bug)。

我发现的唯一方法是颠倒Spark并找出jetty是如何工作的。我使用下面的Nashorn JavaScript代码片段来管理webjars和静态文件,使其一起工作。

除非Spark作者更改他的代码以允许包含特制的上下文处理程序,否则这不会对您有所帮助。但是如果你想在码头追求,那么这个带适应的代码可以帮助你。

此代码适用于Nashorn jjs(来自JDK8),但可以轻松移植到Java。有了这段代码,我可以使用3个独立的webjars 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; 
})();