`
jackyhongvip
  • 浏览: 158189 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

jetty_handler

 
阅读更多

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_指南书》

    ### Jetty6 相关知识点详解 #### 一、Jetty简介 Jetty是一个完全由Java编写的开源HTTP服务器及servlet容器。除了作为一个独立的服务软件外,Jetty还因其高度模块化的设计、低耦合性和高扩展性,被广泛用于嵌入式...

    Jetty6_指南书

    在构架方面,作者深入讲解了Jetty的架构,包括Connector(连接器)、Handler(处理器)、Server和ThreadPool(线程池)等核心组件,让读者了解Jetty如何处理网络请求和应用服务。 配置文件是Jetty管理的关键,书中...

    i-jetty 项目lib和apk源码

    开发者可以通过阅读源码学习如何实现一个Android上的微型服务器,了解Jetty服务器的核心组件,如Request、Response对象,Handler接口等。此外,源码还可能包含了一些示例代码或测试用例,可以帮助开发者快速上手。 ...

    i_jetty安卓端源码

    《深入解析i_jetty安卓端源码》 i_jetty是一款专门为Android平台设计的轻量级Web服务器组件,它基于著名的Java Web服务器Jetty进行优化和定制,为Android应用提供了强大的HTTP服务支持。本文将围绕i_jetty安卓端...

    Jetty工作原理

    Handler是Jetty架构的核心,它是一种可扩展的组件,任何需要添加的功能都可以作为一个Handler,加入到Server中进行管理。 Jetty的基本架构主要由两个关键组件构成:Server和Connector。Server是基于Handler容器运行...

    eclipse整合jetty

    &lt;New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/&gt; &lt;New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/&gt; ``` 注意:上述示例配置文件未...

    Jetty使用总结

    &lt;New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/&gt; &lt;New class="org.mortbay.jetty.webapp.WebAppContext"&gt; &lt;Set name="contextPath"&gt;/jettytest &lt;Set name="war"&gt;./WebRoot...

    jetty 6 指南书

    - **构架概述**:解释Jetty的核心组件,如Connector(连接器)、Handler(处理器)和Server。 - **Connector**:负责网络通信,如HTTP和HTTPS连接的建立。 - **Handler**:处理不同的HTTP请求,如Request Handler...

    jetty源码剖析

    2. 处理请求:Jetty 通过 handler 处理请求,包括解析请求、执行业务逻辑等。 3. 响应请求:Jetty 通过响应客户端的请求。 请求处理下篇 Jetty 的请求处理过程还包括了多个步骤,包括处理 Session、Cookie、 SSL ...

    eclipse中配置使用jetty调试web项目

    &lt;New class="org.eclipse.jetty.server.handler.ContextHandler"&gt; &lt;Set name="contextPath"&gt;/myapp &lt;Set name="resourceBase"&gt;path/to/your/webapp ``` 这段配置将Jetty服务器监听8080端口,并且在"/...

    jetty-all.jar

    Jetty-all.jar是一个集合了众多Jetty组件的综合性JAR文件,它的主要目的是为了方便开发者在项目中快速引入和使用Jetty服务器。Jetty是一个开源的HTTP服务器和Servlet容器,它以其轻量级、高性能和易用性而受到广泛...

    jetty指导书

    Jetty提供了多种Handler类型,每种Handler都有其特定的功能和使用场景。例如: - **ContextHandler**: 负责处理特定上下文路径的请求。 - **ServletContextHandler**: 提供Servlet容器的功能。 - **ResourceHandler...

    jetty所需jar包

    它提供了Server、Connector和Handler等关键接口和实现。 2. **jetty-http.jar**:这个库提供了HTTP协议的实现,包括请求和响应的解析与构建。 3. **jetty-servlet.jar**:Servlet是Java Web开发的标准接口,这个...

    Jetty权威指南.pdf

    Jetty中的Handler组件是处理请求的关键,常见的Handler包括: - **AbstractHandler**:所有Handler的基类。 - **ContextHandler**:用于处理特定上下文路径的请求。 - **DefaultHandler**:默认的Handler,当没有...

    main方法启动jetty

    3. **配置Handler**:Jetty使用Handler来处理HTTP请求。最常见的Handler是`ServletContextHandler`,它可以托管Servlets。创建一个`ServletContextHandler`,并将其添加到Server对象中: ```java ...

    jetty6 指南书

    - **配置文件**:Jetty使用XML配置文件来定制服务器行为,包括Connector、Handler、Server等。 - **部署Web应用**:支持静态和动态部署,包括Servlet2.5的新特性。 6. **Jetty架构**: - **Connector**:负责...

    jetty 嵌入式开发源码

    Jetty采用模块化设计,主要包括Server、Connector、Handler和Servlet等组件。Server是整个框架的核心,负责管理Connectors和Handlers;Connectors负责网络I/O,如HTTP连接;Handlers处理请求并提供响应;Servlet则...

    jetty内嵌到java代码启动

    - 添加Handler:`Handler`是处理HTTP请求的对象,可以是`ServletContextHandler`来处理Servlet,或者`HttpHandler`来处理自定义逻辑。 - 配置Servlet:通过`ServletHolder`注册Servlet,并将其添加到`...

    jetty 源码 2018 zip

    Jetty提供了一系列默认的Handler,例如ContextHandler、ServletHandler、WebSocketHandler等,它们各自负责特定类型的请求处理。 4. **ServletContainer**:Jetty作为Servlet容器,通过ServletHandler来管理Servlet...

    jetty指南书

    Jetty 指南书是一本专注于Jetty web容器的详细教程,主要涵盖了Jetty的基础知识、安装配置、架构解析、服务配置、Web应用程序部署、Handler详解、类加载器、Connector配置、虚拟主机、服务器管理和性能优化等多个...

Global site tag (gtag.js) - Google Analytics