tomcat源码分析学习笔记(五)

来源:互联网 发布:阿里云业务 编辑:程序博客网 时间:2024/06/07 03:08

——每天的寥寥几笔,坚持下去,将会是一份份沉甸甸的积累


上一篇文章讲到了servlet容器的wrapper,这篇继续上一篇来讲讲第二种容器context。

之前讲过context的层次在wrapper之上,可以包含多个wrapper,一个wrapper完成对一个serlvet的处理,多个wrapper的时候,我们就要面临选择,确定到底由哪个wrapper来处理,也就是涉及到了映射查找对应的wrapper。


1.先来看看一个simpleContext

<span style="font-size:12px;">public class SimpleContext implements Context, Pipeline {  public SimpleContext() {    pipeline.setBasic(new SimpleContextValve());//依旧是设置基础阀,同上一篇文章的介绍  }  protected HashMap children = new HashMap();//添加子wrapper  protected Loader loader = null;  protected SimplePipeline pipeline = new SimplePipeline(this);//同上一篇文章  protected HashMap servletMappings = new HashMap();//URL下的servlet与相应wrapper的键值对映射******  //映射器。为了支持不同的协议。注意是协议。比如http,https两个协议,如果请求相同的servlet,处理的wrapper是不一样的  protected Mapper amapper = null;//默认映射器  protected HashMap mappers = new HashMap();//所有可用的映射器,第一个添加到容器中的映射器为默认映射器  private Container parent = null;</span>


2.那又是如何映射查找对应的wrapper。流程如下:

(1)起点定在基础阀(因为基础阀负责创建出serlvet实例,调用service方法)。

<span style="font-size:12px;"> wrapper = (Wrapper) context.map(request, true);</span>


(2)调用Context的map方法,判断传入的request对象的协议是否符合要求,不符合返回null,符合则调用SimpleContextMapper的map方法

<span style="font-size:12px;">  public Container map(Request request, boolean update) {    Mapper mapper = findMapper(request.getRequest().getProtocol());    if (mapper == null)      return (null);    return (mapper.map(request, update));  }</span>


(3)调用SimpleContextMapper的map方法。通过协议的测试后,就直接开始解析requestURL中请求的serlvet名,根据serlvet名映射找到具体wrapper名

<span style="font-size:12px;">public Container map(Request request, boolean update) {    // Identify the context-relative URI to be mapped    String contextPath =      ((HttpServletRequest) request.getRequest()).getContextPath();    String requestURI = ((HttpRequest) request).getDecodedRequestURI();    String relativeURI = requestURI.substring(contextPath.length());    // Apply the standard request URI mapping rules from the specification    Wrapper wrapper = null;    String servletPath = relativeURI;    String pathInfo = null;    String name = context.findServletMapping(relativeURI);//根据serlvet名映射查找serlvetMappings那张hashmap,找到具体wrapper名    if (name != null)      wrapper = (Wrapper) context.findChild(name);//根据上面找到的wrapper名,确定Context的child Wrappper.    return (wrapper);  }</span>


(4)拿到了wrapper,后面的操作同前一篇的操作,可参考tomcat源码分析学习笔记(三)


(5)最后贴上测试的启动类,那就更明晰了。

public final class Bootstrap2 {  public static void main(String[] args) {    HttpConnector connector = new HttpConnector();    Wrapper wrapper1 = new SimpleWrapper();    wrapper1.setName("Primitive");//给wrapper取名    wrapper1.setServletClass("PrimitiveServlet");        Wrapper wrapper2 = new SimpleWrapper();    wrapper2.setName("Modern");    wrapper2.setServletClass("ModernServlet");    Context context = new SimpleContext();    context.addChild(wrapper1);    context.addChild(wrapper2);    Valve valve1 = new HeaderLoggerValve();    Valve valve2 = new ClientIPLoggerValve();    ((Pipeline) context).addValve(valve1);    ((Pipeline) context).addValve(valve2);    Mapper mapper = new SimpleContextMapper();    mapper.setProtocol("http");    context.addMapper(mapper);    Loader loader = new SimpleLoader();    context.setLoader(loader);    // context.addServletMapping(pattern, name);    context.addServletMapping("/Primitive", "Primitive");//添加requestUrl的解析结果和wrapper的映射关系    context.addServletMapping("/Modern", "Modern");    connector.setContainer(context);    try {      connector.initialize();      connector.start();      // make the application wait until we press a key.      System.in.read();    }    catch (Exception e) {      e.printStackTrace();    }  }}


就写到这吧,有什么问题欢迎提出。学生党天天熬夜,也是蛮拼的了。一起加油。



0 0