2015-06-21 47 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; 
})();