Dropwizard Assets 不提供根路径之外的静态内容

Dropwizard Assets not serving static content outside of root path

这是我的 Dropwizard (0.8.5) 应用程序的基本项目结构:

myapp/
    src/main/groovy/
        org/example/myapp/
            MyApp.groovy
            <lots of other packages/classes>
            controllers/
                site/
                    SiteController.groovy
                dashboard/
                    DashboardController.groovy
        org/example/myapp/views
            site/
                SiteView.groovy
            dashboard/
                DashboardView.groovy
    src/main/resources/
        assets/
            images/
                mylogo.png
        org/example/myapp/views/
            site/
                header.ftl
                index.ftl
            dashboard/
                dashboard.ftl

每个 类 的要点是:

class MyApp extends Application<MyAppConfiguration> {
    @Override
    void initialize(Bootstrap<MyAppConfiguration> bootstrap) {
        bootstrap.addBundle(new AssetsBundle('/assets/images', '/images', null, 'images'))
        bootstrap.addBundle(new ViewBundle())
    }

    // etc...
}

@Path('/')
@Produces('text/html')
class SiteController {
    @GET
    SiteView homepage() {
        new SiteView()
    }
}

@Path('/app/dashboard')
@Produces('text/html')
class DashboardController {
    @GET
    DashboardView dashboard() {
        new DashboardView()
    }
}

header.ftl  (dropwizard-views-freemarker)
=========================================
<!DOCTYPE html>
<html>
    <head> <!-- lots of stuff omitted here for brevity --> </head>
    <body>
        <div class="well">
            <img src="images/mylogo.png" />
            <br/>This is the header!
        </div>

index.ftl
=========
<#include "header.ftl">
        <p>
            Homepage!
        </p>
    </body>
</html>

dashboard.ftl
=============
<#include "../site/header.ftl">
        <p>
            Dashboard!
        </p>
    </body>
</html>

所以你可以看到我将 DW 用作实际的网络 app/UI,并且我正在利用两者 Dropwizard Views (Freemarker binding) as well as Dropwizard Assets

当我 运行 这样做时,应用程序启动正常,我可以访问我的主页(从映射到 index.ftl/ 提供)以及我的主页仪表板页面(从映射到 dashboard.ftl/app/dashboard 提供)。

问题是两个页面都使用了 header.ftl,它拉入了我的 assets/images/mylogo.png,但实际上只有我的主页呈现了徽标。 在我的仪表板页面,我 do 看到“This is the header!”消息,所以我知道 header 是正在解决并包含在我的仪表板模板中。 但是,我得到一个 failed-to-load-image "X" 图标,当我打开浏览器的开发工具时,我看到我在图像上收到 HTTP 404。

所以 DW 似乎无法从 view/URL 中找到我的图像资产,而不是直接生活在 root 下(/)。

在 Dropwizard 资产页面(link 上面提供的)有一个特殊的警告:

Either your application or your static assets can be served from the root path, but not both. The latter is useful when using Dropwizard to back a Javascript application. To enable it, move your application to a sub-URL.

我不完全明白这是什么意思,但怀疑它是这里的罪魁祸首。无论哪种方式,有人看到我哪里出了问题,以及我可以做什么(具体步骤!)来解决这个问题?

加载两个页面(一个有效,一个无效),并使用 Firebug 或 Chrome 开发工具检查徽标元素。它试图到达什么路径?我怀疑在您的索引页上它会 http://some.thing/images/mylogo.png whereas on your dashboard it's trying to load http://some.thing/app/dashboard/images/mylogo.png

尝试在模板中的路径前添加一个 /,它应该可以从任何地方解析。

(最初在这里回答:Dropwizard-user Google Group

您需要在您的 URI 前添加 /:

<img src="/images/mylogo.png" />

这个可以从RFC 3986 URI Generic Syntax中的例子中得到解释,我把相关的例子拉出来了

5.4.  Reference Resolution Examples

   Within a representation with a well defined base URI of

      http://a/b/c/d;p?q

   a relative reference is transformed to its target URI as follows.

5.4.1.  Normal Examples

      "g"             =  "http://a/b/c/g"
      "g/"            =  "http://a/b/c/g/"
      "/g"            =  "http://a/g"
      "../g"          =  "http://a/b/g"
      "../../g"       =  "http://a/g"

不管引用的 URI 是什么,在前面加上 / 都会使 URI 从域名开始,这样您就可以精确地执行您想要的操作。