使用Jetty支持Angular 2的PathLocationHandler(使用404错误页面)

时间:2016-10-07 01:00:04

标签: java angularjs jetty embedded-jetty

我试图找出如何使用嵌入式Jetty服务器支持Angular 2的PathLocationHandler。为此,我理解,我需要将任何404请求重定向到顶级index.html文件(https://stackoverflow.com/a/34104534/797

我认为这样做的方法是给ContextHandler和ErrorHandler,它将所有404请求重定向回/index.html,类似下面的代码(我实际上是在上下文xml文件中做的,但是代码可能更容易概念化/调试)。

我看到的是我的错误处理程序被完全忽略了,我不知道如何解决这个错误,或者我不应该如何配置它。

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;

public class JettyTest {

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);

        ResourceHandler resourceHandler = new ResourceHandler();
        resourceHandler.setResourceBase("/tmp/directory-with-just-an-index.html-file");

        ContextHandler contextHandler = new ContextHandler("/context-path");

        ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
        errorHandler.addErrorPage(404, "/index.html");

        contextHandler.setHandler(resourceHandler);
        contextHandler.setErrorHandler(errorHandler);

        server.setHandler(contextHandler);

        server.start();
        System.out.println("Started!");
        server.join();
    }

}

单步执行Jetty代码以获取http://localhost:8080/context-path/some-file-which-is-not-present.html之类的请求,我看到的是ResourceHandler在其资源库中找不到匹配的文件,然后调用...

    //no resource - try other handlers
    super.handle(target, baseRequest, request, response);
    return;

...然后我们从ContextHandler中冒出来,最终HttpChannelOverHttp发出404,因为该请求并未被认为已被处理。

    if (!_response.isCommitted() && !_request.isHandled())
        _response.sendError(404);

也许Jetty期待ResourceHandler以某种不同的方式发出404错误的信号?或者更有可能的是,我没有按照我配置的方式来解释某些事情。

错误配置提示可能是https://www.eclipse.org/jetty/documentation/9.3.x/resource-handler.html提及ResourceHandler"对不存在的资源的请求被允许通过(例如没有404)。",但这让我不清楚在哪里除了“编写自己的处理程序”之外的其他内容'我宁愿避免。

任何指针都非常赞赏!

1 个答案:

答案 0 :(得分:2)

对我来说有些不好的事情让我接触到以下内容,这确实做了我想做的事情,尽管我仍然肯定会接受一个解释为什么ResourceHandler不适合我想要的答案。 ..

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class JettyTest {

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);

        ServletContextHandler servletContextHandler = new ServletContextHandler();
        servletContextHandler.setContextPath("/context-path");
        servletContextHandler.setResourceBase("/tmp/directory-with-just-an-index.html-file");
        servletContextHandler.addServlet(new ServletHolder(new DefaultServlet()), "/*");

        ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
        errorHandler.addErrorPage(404, "/index.html");

        servletContextHandler.setErrorHandler(errorHandler);

        server.setHandler(servletContextHandler);

        server.start();
        System.out.println("Started!");
        server.join();
    }

}

...现在尝试将其转换回xml上下文文件:)

...我最终对以下内容做了以防任何人以后需要它。

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">

<Configure class="org.eclipse.jetty.servlet.ServletContextHandler" id="myContext">

    <Set name="contextPath">/context-path</Set>
    <Set name="resourceBase">/tmp/directory-with-just-an-index.html-file</Set>

    <!-- Direct all 404s to index.html (required by Angular's PathLocationStrategy) -->
    <Set name="errorHandler">
        <New class="org.eclipse.jetty.servlet.ErrorPageErrorHandler">
            <Call name="addErrorPage">
                <Arg type="int">404</Arg>
                <Arg type="String">/index.html</Arg>
            </Call>
        </New>
    </Set>

    <Call name="addServlet">
        <Arg><New class="org.eclipse.jetty.servlet.ServletHolder">
            <Arg>
                <New class="org.eclipse.jetty.servlet.DefaultServlet"></New>
            </Arg>
        </New></Arg>
        <Arg>/*</Arg>
    </Call>

</Configure>