1.handler类图和时序
先上一个handler的继承体系结构图
从上图可以看到,jetty通过一级一级的继承,不断的扩展handler的功能,从最简单的处理到复杂的web容器,下面一一分析之:
然后再看一个简单的请求的handler调用过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
at com.ali.b2b.crm.base.common.filter.LocaleFilter.doFilter(LocaleFilter.java:47) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1322) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:473) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:514) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:920) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:403) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:184) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:856) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:247) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:151) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:114) at org.eclipse.jetty.server.Server.handle(Server.java:352) at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:596) at org.eclipse.jetty.server.HttpConnection$RequestHandler.content(HttpConnection.java:1066) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:805) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:218) at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:426) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:510) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:40) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:450) at java.lang.Thread.run(Thread.java:619) |
2.各种handler分析
2.1 handler接口
1 |
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; |
参数解释:
- target– request的目标, 为URI或者名字.
- baseRequest–最原始的为包装的请求对象.最初server在处理的时候,
- request–可能是最初的request,也可以是在处理过程中被包装过的request
- response–可以是最初的或者被包装过的。
在server解析完http头,构造好request和response传入第一个handler的时候,base quest和quest是一样的,参见server的handle方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public void handle(HttpConnection connection) throws IOException, ServletException { final String target=connection.getRequest().getPathInfo(); final Request request=connection.getRequest(); final Response response=connection.getResponse(); handle(target, request, request, response); } public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (_handler!=null && isStarted()) _handler.handle(target,baseRequest, request, response); } |
当然,handler继承了lifecycle接口,具有生命周期。
2.2 AbstractHandler
一般要自己写handler都会继承于它,最主要就是持有了一个对于server的引用,同时提供了lifeCycle的最简实现。
目前有3个直接继承于abstractHandler的最终实现是DefaultHandler,ResourceHandler和Redirector。
2.3 AbstractHandlerContainer
该类继承自AbstractHandler,同时实现了HandlerContainer接口,并提供了对其的基本实现。主要有两种实现,一种是HandlerCollection,一种是HandlerWrapper。
HandlerCollection的逻辑如下:
1 2 3 4 |
for (int i=0;i<_handlers.length;i++) { _handlers[i].handle(target,baseRequest, request, response); } |
它就是顺序的把所有的handler的handle方法执行一遍。
HandlerWrapper的逻辑如下:
1 2 3 4 5 6 7 |
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (_handler!=null && isStarted()) { _handler.handle(target,baseRequest, request, response); } } |
通过装饰模式,可以嵌套地执行。两者的官方示意图如下:
2.4 ScopedHandler和Server
HandlerWrapper有两个核心的子类,一个是Server,这个比较复杂,以后起专题再谈,
一个是ScopedHandler,目前我的理解,它主要是
For example if Scoped handlers A, B & C were chained together, then
the calling order would be:
A.handle(...) A.doScope(...) B.doScope(...) C.doScope(...) A.doHandle(...) B.doHandle(...) C.doHandle(...)
If non scoped handler X was in the chained A, B, X & C, then the calling order would be:
A.handle(...) A.doScope(...) B.doScope(...) C.doScope(...) A.doHandle(...) B.doHandle(...) X.handle(...) C.handle(...) C.doHandle(...)
ScopedHandler有两个重要属性,一个是_outerScope,一个是_nextScope,outerScope是指一个handerWrapper链里的最外层的继承了ScopedHandler的handler,_nextScope是指下一个继承了ScopedHandler的handler,还有一个ThreadLocal的__outerScope是用了协助初始化的。 其具体的doScope和doHandle是通过如下代码来实现的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public final void nextScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (_nextScope!=null) _nextScope.doScope(target,baseRequest,request, response); else if (_outerScope!=null) _outerScope.doHandle(target,baseRequest,request, response); else doHandle(target,baseRequest,request, response); } public final void nextHandle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (_nextScope!=null && _nextScope==_handler) _nextScope.doHandle(target,baseRequest,request, response); else if (_handler!=null) _handler.handle(target,baseRequest, request, response); } |
ScopedHandler的目的主要是在一个链式的handler中,再实现多次的循环,或者说是一个handler事情做一半,然后由另一个handler做一半,再做剩下的这样的逻辑。ScopedHandler有3个子类,分别是contextHandler,ServletHandler和SessionHandler。基本上他们的doScope逻辑都是如果保存request的上下文,注入新的上下文,待处理完成后再还原以前的上下文,比如contextHandler的简化示例逻辑如下:
1 2 3 4 5 6 7 8 |
public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException old_context=baseRequest.getContext(); if (old_context!=_scontext){ baseRequest.setContext(_scontext); nextScope(); baseRequest.setContext(old_context); } } |
2.5 ContextHandler
顾名思义,是处理context的相关信息的。主要包括设置context,servletPath和classloader。
包含以下核心属性:
_baseResource:resource的根目录,用于ServletContext.getResource()等相关操作
_attributes:实现ServletContext的get和setAtrribute接口,管理context级别的属性信息。
_initParams:ServletContext级别的初始化参数,在web.xml中通过context-param设置,可以通过getServletContext().getInitParameter(“context/param”)得到
_contextListeners:在contextHandler的doStart时回调的listener
比如一个使用例子:
web.xml配置如下:
<context-param>
<param-name>myparam</param-name>
<param-value>1</param-value>
</context-param>
<listener>
<listener-class>MyServletContextListener</listener-class>
</listener>
实现代码如下:
1 2 3 4 5 6 |
public class MyServletContextListener implements ServletContextListener{ public void contextInitialized(ServletContextEvent sce) { String myparam = sce.getServletContext().getInitParameter("myparam"); } } |
事实上在doStart代码的startContext中:
1 2 3 4 5 6 7 8 9 |
if (_contextListeners != null ) { ServletContextEvent event= new ServletContextEvent(_scontext); for (int i= 0; i < LazyList.size(_contextListeners); i++) { ((ServletContextListener)LazyList.get(_contextListeners, i)).contextInitialized(event); } } |
2.6 ServletHandler
这个handler将不同的请求分派给不同的servlet,因此它持有所有web.xml下定义的filter和servlet的引用,以及对应的map关系。
在其doScope方法中,取得对应path的servletHolder:
1 2 3 4 5 6 7 |
if (target.startsWith("/")){ _servletPathMap.getMatch(pathInContext); }else{ servlet_holder=(ServletHolder)_servletNameMap.get(target); } baseRequest.setUserIdentityScope(servlet_holder); |
在其doHandle方法中,取得fileterChain:
1 2 3 4 5 6 7 8 |
ServletHolder servlet_holder=(ServletHolder) baseRequest.getUserIdentityScope(); chain=getFilterChain(baseRequest, null,servlet_holder); if (chain!=null){ chain.doFilter(req, res); }else{ servlet_holder.handle(baseRequest,req,res); } |
2.7 SessionHandler
SessionHandler主要是处理session相关事宜,他的核心属性有一个SessionManager
1 2 3 4 5 6 7 8 9 10 11 12 13 |
if (old_session_manager != _sessionManager) { // new session context baseRequest.setSessionManager(_sessionManager); baseRequest.setSession(null); } HttpSession session=null; if (_sessionManager!=null) { session=baseRequest.getSession(false); } |
这里主要是把_sessionManager set到baseRequest中,具体的每个request的session是在=baseRequest.getSession的时候new出来的。
2.8 ServletContextHandler
Servlet Context, ContextHandler的子类,默认有sessionHandler,securityHandler和servletHandler3个元素,默认只有ServletHandler,但在构造函数中可以选择加上session和security的handler。在doStart的过程中,会创建并初始化3个元素handler,并将其构造成nest handler的链模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
protectedvoid startContext() throws Exception { // force creation of missing handlers. getSessionHandler(); getSecurityHandler(); getServletHandler(); Handler handler = _servletHandler; if (_securityHandler!=null) { _securityHandler.setHandler(handler); handler=_securityHandler; } if (_sessionHandler!=null) { _sessionHandler.setHandler(handler); handler=_sessionHandler; } super.startContext(); _servletHandler.initialize(); } |
链的顺序就是session–>security–>servlet,可以空缺
2.9 WebAppContext
ServletContextHandler的子类,后面起专题讲。
2.9 ContextHandlerCollection
ContextHandlerCollection负责将不同context的请求对应给不同的handler,常规部署中经常是webappContext。
ContextHandlerCollection在请求过程中以请求的最长匹配开始,逐步匹配直到找到合适的contextHandler。注意context的path是设置在各个contexthandler中的。比如我配置一个webAppContext,contextPath为”test”, 一个普通的ContextHandler,设置一个ResourceHandler到其中,contextPath为”test/res”,然后请求 localhost/test/res/a.htm,容器就会先到ResHandler的resourceBase下面去找a.htm,如果找不到,就交给webAppContext去处理。
简化后的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
Object contexts = map.getLazyMatches(target); for (int i=0; i<LazyList.size(contexts); i++){ // then, match against the virtualhost of each context Map.Entry entry = (Map.Entry)LazyList.get(contexts, i); Object list = entry.getValue(); for (int j=0; j<LazyList.size(list); j++){ Handler handler = (Handler)LazyList.get(list,j); handler.handle(target,baseRequest, request, response); if (baseRequest.isHandled()) return; } } |
相关推荐
### Jetty6 相关知识点详解 #### 一、Jetty简介 Jetty是一个完全由Java编写的开源HTTP服务器及servlet容器。除了作为一个独立的服务软件外,Jetty还因其高度模块化的设计、低耦合性和高扩展性,被广泛用于嵌入式...
在构架方面,作者深入讲解了Jetty的架构,包括Connector(连接器)、Handler(处理器)、Server和ThreadPool(线程池)等核心组件,让读者了解Jetty如何处理网络请求和应用服务。 配置文件是Jetty管理的关键,书中...
开发者可以通过阅读源码学习如何实现一个Android上的微型服务器,了解Jetty服务器的核心组件,如Request、Response对象,Handler接口等。此外,源码还可能包含了一些示例代码或测试用例,可以帮助开发者快速上手。 ...
《深入解析i_jetty安卓端源码》 i_jetty是一款专门为Android平台设计的轻量级Web服务器组件,它基于著名的Java Web服务器Jetty进行优化和定制,为Android应用提供了强大的HTTP服务支持。本文将围绕i_jetty安卓端...
Handler是Jetty架构的核心,它是一种可扩展的组件,任何需要添加的功能都可以作为一个Handler,加入到Server中进行管理。 Jetty的基本架构主要由两个关键组件构成:Server和Connector。Server是基于Handler容器运行...
<New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/> <New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/> ``` 注意:上述示例配置文件未...
<New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/> <New class="org.mortbay.jetty.webapp.WebAppContext"> <Set name="contextPath">/jettytest <Set name="war">./WebRoot...
- **构架概述**:解释Jetty的核心组件,如Connector(连接器)、Handler(处理器)和Server。 - **Connector**:负责网络通信,如HTTP和HTTPS连接的建立。 - **Handler**:处理不同的HTTP请求,如Request Handler...
Jetty-all.jar是一个集合了众多Jetty组件的综合性JAR文件,它的主要目的是为了方便开发者在项目中快速引入和使用Jetty服务器。Jetty是一个开源的HTTP服务器和Servlet容器,它以其轻量级、高性能和易用性而受到广泛...
2. 处理请求:Jetty 通过 handler 处理请求,包括解析请求、执行业务逻辑等。 3. 响应请求:Jetty 通过响应客户端的请求。 请求处理下篇 Jetty 的请求处理过程还包括了多个步骤,包括处理 Session、Cookie、 SSL ...
<New class="org.eclipse.jetty.server.handler.ContextHandler"> <Set name="contextPath">/myapp <Set name="resourceBase">path/to/your/webapp ``` 这段配置将Jetty服务器监听8080端口,并且在"/...
Jetty提供了多种Handler类型,每种Handler都有其特定的功能和使用场景。例如: - **ContextHandler**: 负责处理特定上下文路径的请求。 - **ServletContextHandler**: 提供Servlet容器的功能。 - **ResourceHandler...
它提供了Server、Connector和Handler等关键接口和实现。 2. **jetty-http.jar**:这个库提供了HTTP协议的实现,包括请求和响应的解析与构建。 3. **jetty-servlet.jar**:Servlet是Java Web开发的标准接口,这个...
Jetty中的Handler组件是处理请求的关键,常见的Handler包括: - **AbstractHandler**:所有Handler的基类。 - **ContextHandler**:用于处理特定上下文路径的请求。 - **DefaultHandler**:默认的Handler,当没有...
3. **配置Handler**:Jetty使用Handler来处理HTTP请求。最常见的Handler是`ServletContextHandler`,它可以托管Servlets。创建一个`ServletContextHandler`,并将其添加到Server对象中: ```java ...
以下是一个简单的示例代码片段,展示了如何创建一个监听8080端口的Server对象,设置一个默认Handler,并使用XML配置文件(如`jetty.xml`)初始化和启动服务器: ```java public class JettyServer { public static...
- **配置文件**:Jetty使用XML配置文件来定制服务器行为,包括Connector、Handler、Server等。 - **部署Web应用**:支持静态和动态部署,包括Servlet2.5的新特性。 6. **Jetty架构**: - **Connector**:负责...
Jetty采用模块化设计,主要包括Server、Connector、Handler和Servlet等组件。Server是整个框架的核心,负责管理Connectors和Handlers;Connectors负责网络I/O,如HTTP连接;Handlers处理请求并提供响应;Servlet则...
- 添加Handler:`Handler`是处理HTTP请求的对象,可以是`ServletContextHandler`来处理Servlet,或者`HttpHandler`来处理自定义逻辑。 - 配置Servlet:通过`ServletHolder`注册Servlet,并将其添加到`...
Jetty的核心组件包括Server、Connector和Handler。Server是整个Jetty服务器的入口点,Connector负责处理网络连接,而Handler则处理HTTP请求和响应。在指定端口创建TCP服务时,我们需要配置一个Connector,并设置监听...