【问题标题】:Embedded Jetty handling urls to serve content嵌入式 Jetty 处理 url 以提供内容
【发布时间】:2015-11-29 10:19:11
【问题描述】:

我正在使用带有 Guice 的嵌入式 Jetty,并且想知道处理为我的单页应用程序提供服务的最佳方式。

我希望 Jetty 能够像这样处理请求(按优先顺序):

  • /socket 必须由 websocket servlet 处理

  • /fs/read/*,任何与此 url 匹配的内容都需要由自定义 servlet 处理

  • /*,任何与此 url 匹配的内容都应该从 我的 Java 应用程序的类路径上的 /web 假设它不是 以上处理。如果资源不存在,则服务 /web/index.html

现在我想知道处理这个问题的最佳方法是什么?使用 REST 框架似乎很笨拙,因为我真的没有任何休息服务。

这是我目前设置 Jetty 的方式:

ServletHolder servletHolder = new ServletHolder(DefaultServlet.class);

ServletContextHandler servletContextHandler = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
servletContextHandler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
servletContextHandler.addServlet(servletHolder, "/");

ResourceHandler resHandler = new ResourceHandler();
resHandler.setBaseResource(Resource.newClassPathResource("/web"));
server.setHandler(resHandler);

这是我的 Guice ServletModule:

serve("/socket/*").with(WebSocketManagerServlet.class);
serve("/fs/read/*").with(MyCustomServlet.class);

但是,我不确定如何执行最后一条规则,它将任何与index.html 不匹配的内容重定向并且仍然让码头发送正确的标头,这些标头为css/js/html 等提供了正确的 mime 类型。码头也可能这样做我想维护一些内存映射和花哨的东西来快速提供这些服务。

【问题讨论】:

    标签: java servlets jetty guice embedded-jetty


    【解决方案1】:

    一般说明ResourceHandler 不适用于 与具有 ServletContext 的应用程序一起使用。
    ResourceHandler 非常原始(而且非常幼稚),仅用于支持仅使用原始 Jetty 处理程序的 Web 应用程序。
    不要将ResourceHandlerContextHandlerServletContextHandlerWebAppContext 混用。

    根据您的要求,我认为您想要这个......

    URL urlToWebDir = findUrlTo("/web");
    ServletContextHandler servletContextHandler = 
        new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
    servletContextHandler.setContextPath("/");
    servletContextHandler.setWelcomeFiles(new String[] { "index.html" });
    servletContextHandler.setBaseResource(Resource.newResource(urlToWebDir));
    servletContextHandler.addServlet(DefaultServlet.class, "/");
    
    ErrorPageErrorHandler errorMapper = new ErrorPageErrorHandler();
    errorMapper.addErrorPage(404,"/"); // map all 404's to root (aka /index.html)
    servletContextHandler.setErrorHandler(errorMapper);
    

    对于您的"/web" 路径要求,这是一个更简单的设置。

    BaseResource 是 URL(可以是 jar:file://file:// URL 引用),DefaultServlet 使用它来提供静态内容。

    因此,如果/image.png 收到请求,则{baseResource}/image.png 将得到处理(/icons/avatar.gif 上的请求会从{baseResource}/icons/avatar.gif 得到处理

    WelcomeFiles 设置了index.html 解析,因此对/ 的请求会生成服务文件{baseResource}/index.html。 (如果请求是 /alternate/path/deep/in/your/tree/ 然后 /alternate/path/deep/in/your/tree/index.html 被服务(如果存在),也可以工作。

    注意事项:DefaultServlet 支持预压缩静态内容服务。这意味着如果您压缩您的内容并保留一份副本,那么如果他们的浏览器说它支持压缩响应,那么压缩版本就会提供给您的用户。 (例如:使用不支持压缩响应的旧浏览器请求/js/hugelib.js,则提供{baseResource}/js/hugelib.js。但如果浏览器支持压缩响应,则提供{baseResource}/js/hugelib.js.gz

    【讨论】:

    • 这涵盖并适用于所有情况,但/alternate/path/deep/in/your/tree/index.html 不存在的情况除外。在这里,我希望它能够为{baseResource}/index.html 服务。我有一个解决方案,我扩展DefaultServlet 并覆盖doGet。我还不得不将 /web 移出类路径。如果我能找到一个我不必这样做的解决方案,那就太好了。
    • (更新到答案)这是通过自定义 404 错误页面映射完成的。在该示例中,任何 404 都会导致映射到 /(这会导致 /index.html 被服务)。如果您愿意,也可以映射到/index.html。但请注意,这不是一个好主意。因为如果你有一个 404,比如 CSS、Javascript 或图像,那么根 HTML 将被提供(使得整个网页的结果非常奇怪)
    猜你喜欢
    • 2014-03-08
    • 2010-09-09
    • 1970-01-01
    • 2011-01-14
    • 2011-09-15
    • 2012-05-04
    • 1970-01-01
    • 2018-02-12
    • 2014-11-19
    相关资源
    最近更新 更多