Servlet工作原理

一、Servlet工作原理

image

image

当Context容器初始化状态设为init时,添加到Contex容器的Listener将会被调用。ContextConfig继承了LifecycleListener接口,它是在调用Tamcat.addWebapp被加入到StandardContext容器中的。ContextConfig类会负责整个Web应用的配置文件的解析工作。
ContextConfig的init方法将会主要完成以下工作:
◎ 创建用于解析XML配置文件的contextDigester对象。
◎ 读取默认context.xml配置文件,如果存在解析它。
◎ 读取默认Host配置文件,如果存在解析它。
◎ 读取默认Context自身的配置文件,如果存在解析它。
◎ 设置Context的DocBase。
ContextConfig的init方法完成后,Context容器就会执行startInternal方法,这个方法的启动逻辑比较复杂,主要包括如下几个部分:
◎ 创建读取资源文件的对象。
◎ 创建ClassLoader对象。
◎ 设置应用的工作目录。
◎ 启动相关的辅助类,如logger、realm、resources等。
◎ 修改启动状态,通知感兴趣的观察者(Web应用的配置)。
◎ 子容器的初始化。
◎ 获取ServletContext并设置必要的参数。
◎ 初始化“load on startup”的Servlet。

Web应用的初始化工作

Web应用的初始化工作是在ContextConfig的configureStart方法中实现的,应用的初始化主要是解析web.xml文件,这个文件描述了一个Web应用的关键信息,也是一个Web应用的入口。

Tomcat首先会找globalWebXml,这个文件的搜索路径是engine的工作目录下的org/apache/catalin/startup/NO_DEFAULT_XML或conf/web.xml。接着会找hostWebXml,这个文件可能会在System.getProperty("catalina.base")/conf/${EngineName}/${HostName}/ web.xml.default中,接着寻找应用的配置文件examples/WEB-INF/web.xml。web.xml文件中的各个配置项将会被解析成相应的属性保存在WebXml对象中。

如果当前应用支持Servlet 3.0,解析还将完成额外9项工作,这额外的9项工作主要是Servlet 3.0新增的特性(包括jar包中的META-INF/web-fragment.xml)的解析及对annotations的支持。

创建Servlet实例

1.创建Servlet对象

如果Servlet的load-on-startup配置项大于0,那么在Context容器启动的时候就会被实例化,前面提到在解析配置文件时会读取默认的globalWebXml,在conf下的web.xml文件中定义了一些默认的配置项,其中定义了两个Servlet,分别是org.apache.catalina. servlets.DefaultServlet和org.apache.jasper.servlet.JspServlet。
它们的load-on-startup分别是1和3,也就是当Tomcat启动时这两个Servlet就会被启动。
创建Servlet实例的方法是从Wrapper. loadServlet开始的。
loadServlet方法要完成的就是获取servletClass,然后把它交给InstanceManager去创建一个基于servletClass.class的对象。
如果这个Servlet配置了jsp-file,那么这个servletClass就是conf/web.xml中定义的org.apache.jasper.servlet.JspServlet了。

2.初始化Servlet

初始化Servlet在StandardWrapper的initServlet方法中,这个方法很简单,就是调用Servlet的init()方法,同时把包装了StandardWrapper对象的StandardWrapperFacade作为ServletConfig传给Servlet。
Tomcat容器为何要传StandardWrapperFacade给Servlet对象将在后面做详细解析。
如果该Servlet关联的是一个JSP文件,那么前面初始化的就是JspServlet,接下去会模拟一次简单请求,请求调用这个JSP文件,以便编译这个JSP文件为类,并初始化这个类。

image

Servlet体系结构

Servlet主动关联的是三个类,分别是ServletConfig、ServletRequest和ServletResponse。

image

Servlet如何工作
image

Servlet中的Listener

目前Servlet中提供了6种两类事件的观察者接口,它们分别是:
EventListeners类型的ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener
和LifecycleListeners类型的ServletContextListener、HttpSessionListener。

image

Filter如何工作

Filter也是在web.xml中另外一个常用的配置项,可以通过<filter>和<filter-mapping>组合来使用Filter。

在Tomcat容器中,FilterConfig和FilterChain的实现类分别是ApplicationFilterConfig和ApplicationFilterChain,而Filter的实现类由用户自定义,只要实现Filter接口中定义的三个接口就行,这三个接口与Servlet中的类似。
只不过还有一个ApplicationFilterChain类,这个类可以将多个Filter串联起来,组成一个链,这个链与Jetty中的Handler链有异曲同工之妙。下面详细看一下Filter类中的三个接口方法。
◎ init(FilterConfig):初始化接口,在用户自定义的Filter初始化时被调用,它与Servlet的init方法的作用是一样的,FilterConfig与ServletConfig也类似,除了都能取到容器的环境类ServletContext对象之外,还能获取在<filter>下配置的<init-param>参数值。
◎ doFilter ( ServletRequest, ServletResponse, FilterChain):每个用户的请求进来时这个方法都会被调用,这个方法会在Servlet的service方法之前被调用。而FilterChain就代表当前的整个请求链,所以通过调用FilterChain.doFilter可以将请求继续传递下去。如果想拦截这个请求,可以不调用FilterChain.doFilter,那么这个请求就直接返回了。所以Filter是一种责任链设计模式。
◎ destroy:当Filter对象被销毁时,这个方法被调用。注意,当Web容器调用这个方法之后,容器会再调用一次doFilter方法。

image

Servlet中的url-pattern

web.xml中<servlet-mapping>和<filter-mapping>都有<url-pattern>配置项,它们的作用都是匹配一次请求是否会执行这个Servlet或者Filter,那么这个URL是怎么匹配的又是何时匹配的呢?

先看看Servlet是何时匹配的。在Servlet如何工作一节中介绍了一个请求最终被分配到一个Servlet中是通过org.apache.tomcat.util.http.Mapper类完成的,这个类会根据请求的URL来匹配每个Servlet中配置的<url-pattern>,所以它在一个请求被创建时就已经匹配了。
如果这个请求没有匹配到所有的Servlet,那么这个请求就直接返回,也不会有后续的调用任何Filter对象了。

Filter的url-pattern匹配是在创建ApplicationFilterChain对象时进行的,它会把所有定义的Filter的url-pattern与当前的URL匹配,如果匹配成功就将这个Filter保存到ApplicationFilterChain的filters数组中,然后在FilterChain中依次调用。

在web.xml加载时,会首先检查<url-pattern>配置是否符合规则,这个检查是在StandardContext的validateURLPattern方法中检查的,如果检查不成功,Context容器启动会失败,并且会报java.lang.IllegalArgumentException:Invalid<url-pattern> /a/*.htm in Servlet mapping错误。
<url-pattern>的解析规则,对Servlet和Filter是一样的,匹配的规则有三种。
◎ 精确匹配:如/foo.htm只会匹配foo.htm这个URL。
◎ 路径匹配:如/foo/*会匹配以foo为前缀的URL。
◎ 后缀匹配:如*.htm会匹配所有以.htm的URL。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值