`
youyun_2008
  • 浏览: 110777 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

学习tomcat 小记(6)

阅读更多
StandardWrapper

tomcat中有4种类型的container:engine, host, context, wrapper。
一般情况下,context中包含一个或多个wrapper,每个wrapper表示一个servlet定义。

1)方法调用序列
对与每个接收到的http请求,connector调用与其关联的container的invoke方法,然后,container会调用其子container的invoke方法。例如,若connector与一个StandardContext相关联,那么connector会调用StandardContext实例的invoke方法,而StandardContext实例会调用其子container的invoke方法(本例中就是调用StandardWrapper的invoke方法)。

具体过程如下:
(1)connector创建request和response对象;
(2)connector调用StandardContext实例的invoke方法;
(3)StandardContext接着调用其pipeline的invoke方法,StandardContext中pipeline的basic valve是StandardContextValve,因此,StandardContext的pipeline会调用StandardContextValve的invoke方法;
(4)StandardContextValve的invoke方法获取wrapper处理请求,调用wrapper的invoke方法;
(5)StandardWrapper是Wrapper接口的标准实现,StandardWrapper实例的invoke方法会调用其pipeline的invoke方法;
(6)StandardWrapper的pipeline中的basic valve是StandardWrapperValve,因此,会调用其invoke方法,StandardWrapperValve调用wrapper的allocate方法获取servlet实例;
(7)allocate方法调用load方法载入servlet类,若已经载入,则无需重复载入;
(8)load方法调用servlet的init方法;
(9)StandardWrapperValve调用servlet的service方法。


2)SingleThreadModel
若servlet类实现了SingleThreadModel接口,则可以保证绝不会有两个线程同时执行某个servlet的service方法。servlet容器是通过控制对单一servlet实例的同步访问实现,或者维护一个servlet对象池,然后将每个新请求分发到一个新的servlet实例上。该接口并不能防止servlet访问共享资源造成的同步问题,例如访问类的静态变量或访问servlet作用域之外的类。

事实上,实现了SingleThreadModel接口的servlet只保证在同一时刻,只有一个线程在执行servlet的service方法。但是,为了提高效率,servlet容器会创建多个STM servlet实例。也就是说,STM servlet的service方法会在多个STM servlet实例中并发执行。这就有可能引起同步问题。
在servlet2.4中,SingleThreadModel已经被标识为deprecated,因为它会是程序员误以为实现了该接口的servlet就是线程安全的。但,servlt2.3和servlet2.4都还对该接口提供了支持。

3)StandardWrapper
StandardWrapper对象的主要任务是载入它所表示的servlet,并进行实例化。但是,StandardWrapper类并不调用servlet的service方法。该任务由StandardWrapperValve对象(StandardWrapper实例中pipeline的basic valve)完成。StandardWrapperValve对象通过allocate方法从StandardWrapper中获取servlet实例,并调用servlet的service方法。

如果,StandardWrapper通过单例模式使用STM servlet,下面是实现代码:
Servlet instance = <get an instance of the servlet>;
//同步锁的变量instance必须大于该方法范围。

    if (<servlet implementing SingleThreadModel>)  {
      synchronized (instance) {
        instance.service(request, response);
      }
    }
    else {
        instance.service(request, response);
    }
但是,为了更好的性能,StandardWrapper会维护一个STM servlet的对象池。

生成servlet
StandardWrapperValve调用wrapper的allocate方法获取某个指定的servlet对象。StandardWrapper类要负责实现allocate方法。

载入servlet
StandardWrapper类实现了Wrapper接口的load方法,load方法调用loadServlet方法载入servlet类,并调用其init方法(此时要传入一个javax.servlet.ServletConfig实例作为参数)。
loadServlet方法首先会检查当前的StandardWrapper类是不是一个STM servlet,若不是,且变量instance不为null(表示以前已经载入过这个类),就直接返回该引用

ServletConfig对象
StandardWrapper类的loadServlet方法在载入servlet后会调用init方法。init方法需要传入一个javax.servlet.ServletConfig实例作为参数。StandardWrapper类实现了javax.servlet.ServletConfig接口和Wrapper接口。在ServletConfig接口有以下几个方法:getServletContext,getServletName,getInitParameter和getInitParameterNames。接下来分别说明这几个方法的实现。
注意,StandardWrapper类并不将自身实例传给init方法,而是将自身的包装类StandardWrapperFacade的实例传入,这样就很好的将一些public方法隐藏起来了,防止被servlet程序员调用。


StandardWrapperValve类

StandardWrapperValve类是StandardWrapper实例的basic valve,要做两件事:
(1)执行与该servlet关联的全部过滤器 ;
(2)调用servlet的service方法。

为完成上述任务,在StandardWrapperValve的invoke方法中会做以下几件事:
(1)获取servlet实例;
(2)调用私有方法createFilterChain,创建过滤器链;
(3)调用过滤器链的doFilter方法,包括调用servlet的service方法;
(4)释放过滤器链;
(5)调用wrapper的deallocate方法;
(6)若该servlet再也不会被使用到,调用wrapper的unload方法。


FilterDef类
org.apache.catalina.deploy.FilterDef类表示了一个filter定义

ApplicationFilterConfig类
org.apache.catalina.core.ApplicationFilterConfig类实现了javax.servlet.FilterConfig接口。ApplicationFilterConfig类用于管理web应用中的filter。通过传入一个org.apache.catalina.Context实例和一个FilterDef实例创建一个ApplicationFilterConfig实例。

ApplicationFilterChain类
org.apache.catalina.core.ApplicationFilterChain类实现了javax.servlet.FilterChain接口,StandardWrapperValve对象的invoke方法会创建ApplicationFilterChain对象,并调用其doFilter方法。ApplicationFilterChain类的doFilter方法会调用过滤器链中第一个过滤器的doFilter方法。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics