Jetty 9:如何组织处理程序& setWelcomeFiles

时间:2014-12-14 23:55:36

标签: java servlets jetty handler

我使用的是嵌入式Jetty 9,其中Jetty是我应用程序的一个小角落。我有静态内容,servlet和jsp的混合。我的servlet和jsp是我的源代码树的一部分,进入可执行jar并遵循正常的包结构。也许我的一些静态内容将在jar中,但其他静态内容,包括index.html应该放在项目的根文件夹中;它可以作为网络内容存在于子文件夹中。我的servlet和jsp被编译到bin类树的某个地方。

我创建了一个HandlerList,它有servletContext(servlet),resource_handler(静态内容),webAppContext(jsp)&的DefaultHandler。我的resource_handler将WelcomeFiles设置为“index.html”,将ResourceBase设置为“./web-content”。

我玩过HandlerList的不同排序。如果我把resource_handler放在第一位, 然后主页工作正常,但然后resource_handler可以吃其他文件。如果我将resource_handler放在最后,那么主页将获得404。

列表中的第一个可以正常工作,但是当它是第二个或第三个时我会遇到问题。

我知道每个处理程序都尝试处理上下文路径,如果不能,则将其传递给下一个。我不太清楚下一个处理程序的上下文路径。它是否转到基本上下文/或是从前一个处理程序停止的位置继续。为什么不看我的index.html?

我希望能够将内容,静态,servlet或jsp(几乎)放在我想要的任何地方,并在浏览器和具有/的上下文的主页上选择上下文路径。然后让服务器找到它。

这是嵌入的,所以我不需要遵守战争规则。

组织/订购处理程序的规则是什么 - context - welcomeFiles?

1 个答案:

答案 0 :(得分:2)

我正在制定一些规则来回答我的问题,主要是通过实验。

1。将ResourceHandler用于静态内容时,请勿使用setContextPath(“/”),因为它会匹配太多。

2。对于每个上下文路径,使用不同的路径,例如ResourceHandler(1)使用(例如)/ static1,对于ResourceHandler(2)使用/ static2,用于servlet use / servlet。因为没有“/”路径,每个路径都可以轻松映射到它应该服务的内容。

3。不使用 。或者*在ResourceHandler上下文路径上,只是/ foo not / foo / *或./foo

4。在servlet路径上,使用*表示pathInfo,使用(例如)/ servlet / *。然后在servlet中使用request.getPathInfo()来整理*。
中的那些

5。对于setWelcomeFiles,只需使用“index.html”。完成路径的其余部分,如6。

6。将index.html放在say / web(在src旁边),然后放入相应的ResourceHandler,setResourceBase =“web”(没有斜杠=相对路径)。然后它(很容易)不在可运行的罐子里

6a上。如果你想在jar中将它放在Main.java旁边的/ resources包中,那么Eclipse导出将打包jar而不需要求助于Ant。 (可能必须在这里摆弄loadResource()?

7。在ContextHandlerCollection中对ResourceHandler进行分组,因为“它根据上下文路径 创建了包含处理程序 的PathMap”,然后将它们包含在下面的8中。

8。使用HandlerCollection来收集Servlet,因为“它在 列表顺序 中调用所有处理程序,无论响应状态如何”。包括7的集合。

9。请注意,在index.html中,路径可以相对于为此示例中为index.html,/ static1提供服务的ResourceHandler设置的上下文路径。因此,使用servlet的绝对链接将类似于href =“/ servlet / help”和浏览器localhost:80/servlet/help。 (或在相对路径上构建方案)

就我而言。但事情开始奏效。我使用没有xml配置的嵌入式jetty。我还没有合并我的jsp,但我希望我现在有足够的“规则”来做到这一点。

专家评论或扩展/简化这​​些经验规则会有好处!

(编辑)

为什么会这样?

当我使用第二个ResourceHandler时,它提供内容ok(如浏览器所示),但随后会出现IllegalStateException。 要查看发生了什么,我会覆盖ResourceHandler.handle方法,只需使用super.handle()记录请求和isComitted()。 isComitted()显示为true。但是,从句柄返回时,我看到日志消息:

INFO WebServer.configureResourceHandler(2)  target=/foo/bar.bar  request url=http:\\192.168.2.106:8080/static2/foo/bar.bar,  isCommitted=true
WARNING ######  org.eclipse.jetty.server.Response.Committed before 404 null
WARNING ######  org.eclipse.jetty.servlet.ServletHandler./static2/foo/bar.bar
WARNING ######  org.eclipse.jetty.server.HttpChannel./static2/foo/bar.bar
WARNING ######  org.eclipse.jetty.server.HttpChannel.Could not send response error 500: java.lang.IllegalStateException: Committed

似乎ResourceHandler.handle()方法已经提供了内容ok(根据浏览器)并将isComitted设置为true,但handle()之后的代码不知道它已被处理,想要做一个404,但不能这样记录500(由于响应已提交,它无法发送)。

我做错了什么或这是一个错误?

应答

不是错误。我正在将ContextHandlerCollection项与HandlerCollection项混合使用。前者通过上下文路径过滤,后者不是。所以我的servlet试图处理已处理的项目。通过以与静态内容相同的方式处理servlet来解决这个问题。使用这样的代码:

private ContextHandler configureRootServlet() {
        ServletContextHandler context = new ServletContextHandler(); /* Can hold several servlets */
        context.setContextPath( "/servlet" );
        ServletHandler handler = new ServletHandler();
        context.setHandler( handler );
        handler.addServletWithMapping( RootServlet.class, "/*"); 
        rootServlet = (RootServlet)handler.getServlets()[0].getServlet();/*We 
        only added one. Grab the servlet instance he created for us so we can 
        configure it */
        // Configure the servlet
        rootServlet.setMain( mainClass );
        // etc
        return context;
}

然后只需将ServletContextHandler添加到ContextHandlerCollection中。请注意,servlet映射与上下文相关。把它全部包裹起来......

ContextHandlerCollection contexts = new ContextHandlerCollection();
        contexts.setHandlers(new Handler[]{ configureResourceHandler1()
                , configureResourceHandler2(), configureRootServletHandler() });
        HandlerCollection handlers = new HandlerCollection();
        handlers.setHandlers( new Handler[]{ contexts, new DefaultHandler()
        ,configureRequestLogHandler() });

现在没有服务器错误!