学习tomcat 小记(6)

[size=medium]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实例上。[color=red]该接口并不能防止servlet访问共享资源造成的同步问题,例如访问类的静态变量或访问servlet作用域之外的类。[/color]

事实上,实现了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,下面是实现代码:
[color=blue]Servlet instance = <get an instance of the servlet>;
//同步锁的变量instance必须大于该方法范围。[/color]
if (<servlet implementing SingleThreadModel>) {
synchronized (instance) {
instance.service(request, response);
}
}
else {
instance.service(request, response);
}
但是,为了更好的性能,StandardWrapper会维护一个STM servlet的对象池。

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

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

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

[color=blue]
StandardWrapperValve类[/color]
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方法。


[color=darkblue]FilterDef类[/color]
org.apache.catalina.deploy.FilterDef类表示了一个filter定义

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

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

[/size]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值