Servlet工作原理摘要

Servlet容器是如何工作的

Context容器直接管理Servlet的包装类Wrapper

Tomcat public addWebapp() {创建Context(StandardContext),ConextConfig配置}

ContextConfig:负责完成整个Web应用的配置文件解析工作

ContextConfig的init:{

创建用于解析XML的contextRegister对象。
读取默认的context.xml,如果存在则解析它。
读取默认的Host配置文件,如果存在则解析它。
读取默认的Context自身的配置文件,如果存在则解析它。
设置Context的DocBase。//应用实际的物理路径

}

Context容器:startInternal:
{

创建读取资源的对象
创建ClassLoader对象
设置应用的工作目录
启动相关的辅助类
修改启动状态,通知感兴趣的观察者
子容器初始化  
获取Servlet并设置必要的参数
初始化Servlet(load on startup)

}

Servlet容器在web工程中是如何启动和如何解析web.xml

Web应用的初始化开始于ContextConfig.configureStart方法中实现的。主要是解析web.xml文件,web应用的关键信息,web应用的入口。

Tomcat需要globalWebXml和hostWebXml

  1. 查找:C:\apache-tomcat-7.0.56\conf\web.xml
  2. 寻找应用程序的web.xml文件,如/WEB-INF/web.xml,WebXml对象解析。

启动,

  1. 设置JSP
  2. 设置加载时启动LoadOnStartup
  3. 判断Servlet是否Enable
  4. 初始化initParameter
  5. 设置安全参考信息
  6. 设置wrapper的Class类
  7. 设置Servlet是否允许的文件上传的,MultiPartFile…之类的。
  8. 设置是否支持异步

最后添加到context托管。

for(ServletDef servlet:servlets.values){
    Wrapper wrapper =context.createWrapper();
    String jspFile=servlet.getJspFile();
    wrapper.setJspFile(jspFile);
    wrapper.setName(servlet.getServletName);
    wrapper.setServletClass(servlet.getServletClass());


.....
context.addChild(wrapper);
}

这里:生成的Servlet的包装类Wrapper,而不是具体的Servlet对象,原因是Wrapper类是Tomcat容器的一部分,具有容器的特性,而Servlet是web开发的标准,不作耦合。

一个Web应用对应于一个Context容器,所以真正管理Servlet的是Context容器,容器的配置属性由web.xml设置的。

生成Servlet对象

Wrapper.loadServlet—>获取ServletClass.class—>InstanceManager生成ServletClass.class对应的对象。

**StandardContext.lifecycleEvent()–>ContextConfig.configureStart()—>webConfig—>new WebXml–>parseWebXml(globalWebXml,hostWebXml)—>configureContext()–>set(属性全设置到容器中)—>Wrapper.createWrapper()—>set(Wrapper的各种属性,包括ServletClass.class)—>
Context.addChild(wrapper)—>设置其他属性如(servletMapping)—>容器执行StartInternal==>加载资源,启动其他组件如Logger,realm==>loadOnStartup==>load。
StandardWrapper.loadServlet()–>InstanceManager.newInstance()–>initServlet()–>init(this.facade)**

this.facade是StandardWrapperFacade类实例,该类实现ServletConfig接口,并持有ServletConfig的一个实现类StandardWrapper的引用,并暴露出部分数据(足够生成Servlet)称为:门面设计模式。

用户请求是如何分配给指定Servlet的

Servlet 如何工作

http://hostname:port/contextpath/servletpath, hostname+port用于TCP连接。
org.apache.tomcat.util.http.mapper //完成根据URL选择服务器中哪种子容器来服务请求。这个类保存Tomcat中的Container所有子容器信息。在Request类进入Container容器之前,Mapper会根据Hostname和ContextPath,将hostname和context设置到Request类中的mappingData中,这样在还没有进入到Container之前就已经确定了要访问哪个容器。

为何mapper含有全部信息,原因是存在MapperListener,对容器进行监听,在容器发生变化的时候,Mapper对应的属性也会更改。
在Mapper.init过程中将host下面的子容器注册到Mapper中。

Filter如何工作

定义在web.xml的filter配置项中,和组合使用。除了Request和Response对象,还给了一个FilteChain对象,更灵活地控制跳转。

找了一个源码org\springframework\web\filter\CompositeFilter.java。然后找到doFilter方法

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response)
            throws IOException, ServletException {

        if (this.currentPosition == this.additionalFilters.size()) {
            this.originalChain.doFilter(request, response);
        }
        else {
            this.currentPosition++;
            Filter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
            nextFilter.doFilter(request, response, this);
        }
    }

基本思想就是用一个position指针指向当前位置,如果filter没有到最后这接着往下执行,直到最后。

看了源码然后发现FilterChain链条的实现似曾相识,果不其然:
http://blog.csdn.net/Newpidian/article/details/53925448
这篇博客写的是实现链式AOP动态代理,实现起来的结果就像这样。

    a.before()
           b.before()
           result=targetMethod.invokeSuper();
           b.after()
    a.after()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值