tomcat请求处理分析(二) 启动mapperListener

来源:互联网 发布:人工智能 龙头 编辑:程序博客网 时间:2024/06/07 01:31

1.1.1启动mapperListener 

   这个方法的核心就是注册Host的

  

public void startInternal()throws LifecycleException{

    setState(LifecycleState.
STARTING);
   
//获取当前servicecontainer,其实也就是engine
   
@SuppressWarnings("deprecation")
    Engine engine = (Engine)
service.getContainer();
    if
(engine == null) {
       
return;
   
}

    findDefaultHost()
;//获取当前engine默认的host
   
addListeners(engine);//给当前Mapper添加监听时间

    //
找到当前engine下所有host主机
   
Container[] conHosts =engine.findChildren();
    for
(Container conHost :conHosts) {
        Host host = (Host) conHost
;
        if
(!LifecycleState.NEW.equals(host.getState())){
           
// 登记host会注册context wrappers
           
registerHost(host);
       
}
    }

}

 

1.1.1.1  注册Host

 注册Host主要进行了两步操作,第一步是添加Host 第二步是registerContext

private void registerHost(Host host) {

    String[] aliases = host.findAliases()
;
   
mapper.addHost(host.getName(),aliases, host);

    for
(Container container :host.findChildren()) {
       
if (container.getState().isAvailable()){
            registerContext((Context)container)
;
        
}
    }
   
if(log.isDebugEnabled()){
       
log.debug(sm.getString("mapperListener.registerHost",
               
host.getName(),domain, service));
   
}
}

 

1.1.1.1.1     添加Host

   

public synchronizedvoid addHost(String name,String[]aliases,
                                
Host host) {
   
//StandardEngine[Catalina].StandardHost[localhost]
    //创建MappedHost对象的数组,这里长度需要加1
    MappedHost[]newHosts = newMappedHost[hosts.length+ 1];
   
//创建一个MappedHost对象,用于保存host的map信息
    MappedHostnewHost = newMappedHost(name,host);
   
//insertMap将hosts这个数组迁移到newHosts并将newHost按name添加到指定位置
    if (insertMap(hosts,newHosts, newHost)) {
       
hosts= newHosts;  //指向新的数组
        if (log.isDebugEnabled()) {
           
log.debug(sm.getString("mapper.addHost.success",name));
       
}
    }
else{
       
//不能插入这说明有相同名字的,有两种情况,第一种是在先前通过addContextVersion加入让那个newHost指向,另一种名字相同则直接返回
        MappedHostduplicate = hosts[find(hosts,name)];
        if
(duplicate.object== host) {
            if(log.isDebugEnabled()) {
               
log.debug(sm.getString("mapper.addHost.sameHost",name));
           
}
            newHost = duplicate
;
       
}else{
           
log.error(sm.getString("mapper.duplicateHost",name,
                   
duplicate.getRealHostName()));
            return;
       
}
    }
    List<MappedHost> newAliases =
new ArrayList<>(aliases.length);
    for
(Stringalias : aliases) {
        MappedHost newAlias =
new MappedHost(alias,newHost);
        if
(addHostAliasImpl(newAlias)) {
            newAliases.add(newAlias)
;
       
}
    }
    newHost.addAliases(newAliases)
;
}

    这个方法的作用将新的host插入到已有的集合,如果存在,直接返回,不存在则按字母排序有序插入,其中实现有序插入主要是调用了find这个二分查找,找到跟当前name最近的一个,然后进行插入,数组迁移

private static final <T>boolean insertMap
   
(MapElement<T>[]oldMap,MapElement<T>[] newMap,MapElement<T>newElement) {
   
int pos =find(oldMap, newElement.name);//old里面,最近接新的元素的name的位置,这里返回的pos要么name相当,要么最左侧
   
if ((pos != -1) &&(newElement.name.equals(oldMap[pos].name))) { //这里表示有名字相同的,那么失败
       
return false;
   
}
   
//分段拷贝,这样拷贝完了之后也是排好序的
   
System.arraycopy(oldMap,0, newMap,0, pos +1);//对数组拷贝,这里相当于先拷贝小的
   
newMap[pos + 1] =newElement;
   
System.arraycopy
       
(oldMap
, pos +1, newMap,pos + 2,oldMap.length- pos - 1);
    return true;
}

 

二分查找方法如下:

private static final <T>int find(MapElement<T>[] map,String name){

   
int a =0;
    int
b = map.length- 1;

   
// Special cases: -1 and 0
   
if (b == -1) {
       
return -1;
   
}

   
if (name.compareTo(map[0].name) <0) {
       
return -1;
   
}
   
if (b ==0) {
       
return 0;
   
}

   
int i =0;
    while
(true) {
        i = (b + a) /
2;
        int
result =name.compareTo(map[i].name);
        if
(result > 0) {
            a = i
;
       
} else if(result == 0) {
           
return i;
       
} else{
            b = i
;
       
}
       
if ((b - a) ==1) {
           
int result2 =name.compareTo(map[b].name);
            if
(result2 < 0) {
               
return a;
           
} else{
               
return b;
           
}
        }
    }

}

1.1.1.1.2     注册web应用

  在这里注册路由,经过http请求能够找到对应的web 应用,一个context对应一个web应用

private void registerContext(Context context) {

    String contextPath =context.getPath()
; //获取context的路径
   
if ("/".equals(contextPath)){
        contextPath =
"";
   
}
    Host host = (Host)context.getParent()
; //获取的其host
   
WebResourceRootresources = context.getResources();//获取root
   
String[] welcomeFiles =context.findWelcomeFiles();//获取欢迎页


    //
准备context 下的所有 wrapper 信息
   
List<WrapperMappingInfo>wrappers = new ArrayList<>();
    for
(Container container :context.findChildren()) {
        prepareWrapperMappingInfo(context
, (Wrapper)container,wrappers);

        if
(log.isDebugEnabled()){
           
log.debug(sm.getString("mapperListener.registerWrapper",
                   
container.getName(),contextPath,service));
       
}
    }

   
// 添加 contextVersion在这里面会将该context下的所有wrapper映射信息也构建
   
mapper.addContextVersion(host.getName(),host, contextPath,
           
context.getWebappVersion(),context, welcomeFiles, resources,
           
wrappers);

    if
(log.isDebugEnabled()){
       
log.debug(sm.getString("mapperListener.registerContext",
               
contextPath,service));
   
}

}