简体   繁体   English

码头9:如何组织处理程序和setWelcomeFiles

[英]Jetty 9: How to organise handlers & setWelcomeFiles

I am using embedded Jetty 9 where Jetty is a small corner of my application. 我正在使用嵌入式Jetty 9,其中Jetty是我的应用程序的一小部分。 I have a mix of static content, servlets and jsp's. 我混合了静态内容,servlet和jsp。 My servlets and jsp's are part of my source tree and go into the executable jar and follow a normal package structure. 我的servlet和jsp是我的源代码树的一部分,进入可执行jar,并遵循正常的包结构。 Perhaps some of my static content will be in the jar, but other static content, including index.html should go in the project root folder; 也许我的一些静态内容会放在jar中,但是其他静态内容(包括index.html)应该放在项目的根文件夹中。 it could be in a sub-folder as web-content. 它可能位于网络内容的子文件夹中。 My servlets and jsp's are compiled somewhere into the bin class tree. 我的servlet和jsp被编译到bin类树中。

I create a HandlerList having servletContext(servlet), resource_handler(static content), webAppContext(jsp) & DefaultHandler. 我创建一个具有ServletContext(servlet),resource_handler(静态内容),webAppContext(jsp)和DefaultHandler的HandlerList。 My resource_handler sets WelcomeFiles to "index.html" and ResourceBase to "./web-content". 我的resource_handler将WelcomeFiles设置为“ index.html”,将ResourceBase设置为“ ./web-content”。

I have played with different orderings of the HandlerList. 我玩过不同的HandlerList顺序。 If I put resource_handler first, then the home page works fine, but then resource_handler can eat other files. 如果我先放置resource_handler,则主页工作正常,但是resource_handler可以使用其他文件。 If I put resource_handler last, then home page gets 404's. 如果我把resource_handler放在最后,那么主页将得到404。

Which ever is first in the list works fine but I get problems when it is second or third. 列表中的第一个可以正常工作,但是第二或第三个出现问题。

I know that each handler tries to handle the context path and if it can't, passes it to the next. 我知道每个处理程序都尝试处理上下文路径,如果不能处理,则将其传递给下一个。 I am less clear about the context path the next handler starts with. 我不太了解下一个处理程序开始的上下文路径。 Does it go to the base context / or does it continue from where the previous handler left off. 它是转到基本上下文,还是从上一个处理程序中断的地方继续。 Why doesn't it see my index.html? 为什么看不到我的index.html?

I would like to be able to put content, static, servlet or jsp (almost) wherever I want and have context paths chosen to seem logical at the browser and a home page with a context of /. 我希望能够(几乎)将内容,静态,servlet或jsp(几乎)放在任何地方,并选择上下文路径以使其在浏览器和带有/上下文的主页上看起来合乎逻辑。 And then have the server find it. 然后让服务器找到它。

This is embedded so I do not need to conform to war rules. 这是嵌入式的,因此我不需要遵守战争规则。

What are the rules to organize/order handlers - context - welcomeFiles? 组织/排序处理程序-上下文-welcomeFiles的规则是什么?

I am evolving some rules to answer my question, largely by experiment. 我主要通过实验制定一些规则来回答我的问题。

1. When using ResourceHandler for static content, do NOT use setContextPath("/") as it will match too much. 1.当对静态内容使用ResourceHandler时,请勿使用setContextPath(“ /”),因为它会太多匹配。

2. For each context path, use a distinct path for example for ResourceHandler(1) use (say) /static1, for ResourceHandler(2) use /static2, for a servlet use /servlet. 2.对于每个上下文路径,请使用不同的路径,例如,对于ResourceHandler(1)使用(例如)/ static1,对于ResourceHandler(2)使用/ static2,对于Servlet使用/ servlet。 Because there is no "/" path each easily maps to what it should serve. 因为没有“ /”路径,所以每个路径都容易映射到其应服务的内容。

3. Do not use . 3.请勿使用。 or * on ResourceHandler context paths, just /foo not /foo/* or ./foo 或*在ResourceHandler上下文路径上,仅/ foo而不是/ foo / *或./foo

4. On servlet paths do use * to represent pathInfo, use (say) /servlet/*. 4.在servlet路径上,请使用*表示pathInfo,请使用(例如)/ servlet / *。 Then in the servlet use request.getPathInfo() to sort out those in *. 然后在servlet中使用request.getPathInfo()来对*中的内容进行排序。

5. For setWelcomeFiles just use "index.html". 5.对于setWelcomeFiles,只需使用“ index.html”。 Do the rest of the path as in 6. 按照6中的其余步骤进行操作。

6. Put index.html in say /web (beside src) then for the corresponding ResourceHandler, setResourceBase="web" (no slash=relative path). 6.将index.html放在/ web(在src旁边)中,然后为相应的ResourceHandler设置setResourceBase =“ web”(无斜杠=相对路径)。 Then it is (easily) not in the runnable jar 然后(轻松)不在可运行的jar中

6a. 6A。 If you want it in the jar put it in a /resources package beside Main.java then Eclipse export will package the jar without resorting to Ant. 如果要在jar中将其放在Main.java旁边的/ resources包中,则Eclipse导出将打包jar,而无需使用Ant。 (may have to fiddle with loadResource() here? (可能必须在这里摆弄loadResource()吗?

7. Group ResourceHandlers in a ContextHandlerCollection since "it creates a PathMap to it's contained handlers based on the context path " then include them with 8 below. 7.将ResourceHandlers分组到ContextHandlerCollection中,因为“它根据上下文路径为其包含的处理程序创建一个PathMap”,然后在下面的8中包括它们。

8. Use HandlerCollection to collect Servlets since "it calls all handlers in list order , regardless of the response status or exceptions". 8.使用HandlerCollection来收集Servlet,因为“它以列表顺序调用所有处理程序,而不管响应状态或异常如何”。 Do include the collection of 7. 包括7的集合。

9. Note that within index.html, paths can be relative to the context path set for the ResourceHandler that serves index.html, /static1 in this example. 9.请注意,在index.html中,路径可以相对于为服务index.html(在本示例中为/ static1)的ResourceHandler设置的上下文路径。 So use absolute links to the servlet will be like href="/servlet/help" and in the browser localhost:80/servlet/help . 因此,使用到servlet的绝对链接将类似于href =“ / servlet / help”并在浏览器中localhost:80/servlet/help ( or build a scheme on relative paths) (或在相对路径上构建方案)

That is as far as I have got. 据我所知。 But things are starting to work. 但是事情开始起作用了。 I am using embedded jetty with no xml configuration. 我正在使用没有xml配置的嵌入式码头。 I didn't merge my jsp's in with this yet, but I hope I have enough 'rules' to do that now. 我还没有将我的jsp与之合并,但是我希望我现在有足够的“规则”来做到这一点。

It would be good for an expert to comment or expand/simplify these empirical rules! 专家对这些经验规则进行评论或扩展/简化,将是一件好事!

(Edit) (编辑)

Why does this happen? 为什么会这样?

When I use the second ResourceHandler, it serves the content ok (as seen on a browser) but then gives IllegalStateException. 当我使用第二个ResourceHandler时,它可以正常显示内容(在浏览器中可以看到),但是会给出IllegalStateException。 To see what is going on, I override ResourceHandler.handle method and just use super.handle() logging the request and isComitted() . 要查看发生了什么,我重写ResourceHandler.handle方法,仅使用super.handle()记录请求和isComitted() isComitted() shows true. isComitted()显示为true。 However, on return from handle I see log messages: 但是,从句柄返回时,我会看到日志消息:

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

It seems that the ResourceHandler.handle() method has served the content ok (according to the browser) and set isComitted true, but code after handle() is not aware that it has been handled, wants to do a 404 but can't so logs a 500 (which it can't send because the response is committed). 似乎ResourceHandler.handle()方法已满足内容要求(根据浏览器)并设置了isComitted true,但是handle()之后的代码不知道它已被处理,想执行404但不能因此记录500(由于已提交响应而无法发送)。

What am I doing wrong or is this a bug? 我在做什么错或者这是一个错误?

Answer 回答

Not a bug. 不是错误。 I am mixing ContextHandlerCollection items with HandlerCollection items. 我将ContextHandlerCollection项目与HandlerCollection项目混合在一起。 The former are filtered by context path, the latter are not. 前者是按上下文路径过滤的,后者则不是。 So my servlet was trying to handle items already handled. 所以我的servlet试图处理已经处理过的项目。 Solve this by dealing with the servlet in the same way as the static content. 通过以与静态内容相同的方式处理servlet来解决此问题。 Use code like this: 使用如下代码:

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;
}

Then just add the ServletContextHandler to the ContextHandlerCollection. 然后只需将ServletContextHandler添加到ContextHandlerCollection。 Note the servlet mapping is relative to the context. 注意,servlet映射是相对于上下文的。 Wrap it all together ... 将它们包装在一起...

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

Now there are no server errors! 现在没有服务器错误!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM