MapperListener.startInternal public void startInternal() throws LifecycleException { setState(LifecycleState.STARTING); Engine engine = service.getContainer(); if (engine == null) { return; } //寻找默认的host,给engine设置默认的host findDefaultHost(); //给engine和子容器添加MapperListener addListeners(engine); //获取所有的host Container[] conHosts = engine.findChildren(); for (Container conHost : conHosts) { Host host = (Host) conHost; if (!LifecycleState.NEW.equals(host.getState())) { // Registering the host will register the context and wrappers registerHost(host); } } } MapperListener.registerHost private void registerHost(Host host) { //获取别名 String[] aliases = host.findAliases(); //添加host mapper.addHost(host.getName(), aliases, host); //注册context 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)); } } Mapper.addHost public synchronized void addHost(String name, String[] aliases, Host host) { //重命名主机通配符,比如*.apache.org,会把开头这种通配符*去掉,变成.apache.org name = renameWildcardHost(name); MappedHost[] newHosts = new MappedHost[hosts.length + 1]; MappedHost newHost = new MappedHost(name, host); //插入到mappedHosts集合中,会用过名字进行排序 if (insertMap(hosts, newHosts, newHost)) { hosts = newHosts; //设置默认的host if (newHost.name.equals(defaultHostName)) { defaultHost = newHost; } if (log.isDebugEnabled()) { log.debug(sm.getString("mapper.addHost.success", name)); } //如果插入失败 } else { //从host集合中查找到这个同名的MappedHost MappedHost duplicate = hosts[find(hosts, name)]; //如果这个MappedHost中的host和当前的host是同一个 if (duplicate.object == host) { // The host is already registered in the mapper. // E.g. it might have been added by addContextVersion() if (log.isDebugEnabled()) { log.debug(sm.getString("mapper.addHost.sameHost", name)); } //将这个已经存在的host复制给newHost newHost = duplicate; } else { //如果存在同名的host并且和注册的host不一样,那么直接返回,不对别名进行注册 log.error(sm.getString("mapper.duplicateHost", name, duplicate.getRealHostName())); // Do not add aliases, as removeHost(hostName) won't be able to // remove them return; } } List<MappedHost> newAliases = new ArrayList<>(aliases.length); for (String alias : aliases) { //重命名别名,和上面重命名name是一样的操作 alias = renameWildcardHost(alias); MappedHost newAlias = new MappedHost(alias, newHost);//持有真实的MappedHost if (addHostAliasImpl(newAlias)) { newAliases.add(newAlias); } } newHost.addAliases(newAliases); } Mapper.insertMap(hosts, newHosts, newHost) private static final <T> boolean insertMap (MapElement<T>[] oldMap, MapElement<T>[] newMap, MapElement<T> newElement) { //寻找可以插入的位置,按照name进行从小到大排序 int pos = find(oldMap, newElement.name); //如果新host的name和已经存在的host的名字一样,那么表示已经存在了,插入失败 if ((pos != -1) && (newElement.name.equals(oldMap[pos].name))) { return false; } //将旧的host集合copy的到新的host集合中 System.arraycopy(oldMap, 0, newMap, 0, pos + 1); newMap[pos + 1] = newElement; //将旧得剩余的hostcopy到新数组中 System.arraycopy (oldMap, pos + 1, newMap, pos + 2, oldMap.length - pos - 1); return true; } Mapper.find() private static final <T> int find(MapElement<T>[] map, String name) { int a = 0; int b = map.length - 1; // Special cases: -1 and 0 如果旧的hosts集合没有任何东西,直接返回-1,表示可以直接从零位置插入 if (b == -1) { return -1; } //如果新的host比第一个位置的host小,那么直接返回-1,从零位置插入 if (name.compareTo(map[0].name) < 0) { return -1; } //如果host结合中存在一个元素,并且这个元素不比零位置的host小,那么返回零,插入到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; } } } } Mapper.addHostAliasImpl //这段代码和addHost上部分 private synchronized boolean addHostAliasImpl(MappedHost newAlias) { MappedHost[] newHosts = new MappedHost[hosts.length + 1]; if (insertMap(hosts, newHosts, newAlias)) { hosts = newHosts; if (newAlias.name.equals(defaultHostName)) { defaultHost = newAlias; } if (log.isDebugEnabled()) { log.debug(sm.getString("mapper.addHostAlias.success", newAlias.name, newAlias.getRealHostName())); } return true; } else { MappedHost duplicate = hosts[find(hosts, newAlias.name)]; if (duplicate.getRealHost() == newAlias.getRealHost()) { // A duplicate Alias for the same Host. // A harmless redundancy. E.g. // <Host name="localhost"><Alias>localhost</Alias></Host> if (log.isDebugEnabled()) { log.debug(sm.getString("mapper.addHostAlias.sameHost", newAlias.name, newAlias.getRealHostName())); } return false; } log.error(sm.getString("mapper.duplicateHostAlias", newAlias.name, newAlias.getRealHostName(), duplicate.getRealHostName())); return false; } } Mapper.registerContext private void registerContext(Context context) { String contextPath = context.getPath(); if ("/".equals(contextPath)) { contextPath = ""; } Host host = (Host)context.getParent(); WebResourceRoot resources = context.getResources(); String[] welcomeFiles = context.findWelcomeFiles(); 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)); } } //添加context版本 mapper.addContextVersion(host.getName(), host, contextPath, context.getWebappVersion(), context, welcomeFiles, resources, wrappers); if(log.isDebugEnabled()) { log.debug(sm.getString("mapperListener.registerContext", contextPath, service)); } } MapperListener.prepareWrapperMappingInfo private void prepareWrapperMappingInfo(Context context, Wrapper wrapper, List<WrapperMappingInfo> wrappers) { String wrapperName = wrapper.getName(); boolean resourceOnly = context.isResourceOnlyServlet(wrapperName); String[] mappings = wrapper.findMappings(); //以映射为维度,添加每个wrapper for (String mapping : mappings) { boolean jspWildCard = (wrapperName.equals("jsp") && mapping.endsWith("/*")); wrappers.add(new WrapperMappingInfo(mapping, wrapper, jspWildCard, resourceOnly)); } } Mapper.addContextVersion public void addContextVersion(String hostName, Host host, String path, String version, Context context, String[] welcomeResources, WebResourceRoot resources, Collection<WrapperMappingInfo> wrappers) { hostName = renameWildcardHost(hostName); //精确查找MappedHost,如果不存在,那么就加入 MappedHost mappedHost = exactFind(hosts, hostName); if (mappedHost == null) { addHost(hostName, new String[0], host); mappedHost = exactFind(hosts, hostName); if (mappedHost == null) { log.error("No host found: " + hostName); return; } } //是否是别名,如果是别名,那么对应的正统host和当前的对象不一致,直接返回 if (mappedHost.isAlias()) { log.error("No host found: " + hostName); return; } //计算路径中/的个数 int slashCount = slashCount(path); synchronized (mappedHost) { //创建当前context版本 ContextVersion newContextVersion = new ContextVersion(version, path, slashCount, context, resources, welcomeResources); if (wrappers != null) { //将wrappers进行分类,通配符wrapper,扩展型,精确型wrapper集合 addWrappers(newContextVersion, wrappers); } ContextList contextList = mappedHost.contextList; MappedContext mappedContext = exactFind(contextList.contexts, path); if (mappedContext == null) { mappedContext = new MappedContext(path, newContextVersion); //添加mappedContext到 ContextList中 ContextList newContextList = contextList.addContext( mappedContext, slashCount); if (newContextList != null) { //返回了新的集合后,需要替换掉MappedHost与别名中的contextList updateContextList(mappedHost, newContextList); //将context对象和对应版本添加到map中 contextObjectToContextVersionMap.put(context, newContextVersion); } } else { //获取版本版本 ContextVersion[] contextVersions = mappedContext.versions; ContextVersion[] newContextVersions = new ContextVersion[contextVersions.length + 1]; //插入版本,如果对应的版本已经存在,那么直接替换掉。 if (insertMap(contextVersions, newContextVersions, newContextVersion)) { mappedContext.versions = newContextVersions; contextObjectToContextVersionMap.put(context, newContextVersion); } else { // Re-registration after Context.reload() // Replace ContextVersion with the new one int pos = find(contextVersions, version); if (pos >= 0 && contextVersions[pos].name.equals(version)) { contextVersions[pos] = newContextVersion; contextObjectToContextVersionMap.put(context, newContextVersion); } } } } } Mapper.addWrapper protected void addWrapper(ContextVersion context, String path, Wrapper wrapper, boolean jspWildCard, boolean resourceOnly) { synchronized (context) { if (path.endsWith("/*")) { // Wildcard wrapper String name = path.substring(0, path.length() - 2); MappedWrapper newWrapper = new MappedWrapper(name, wrapper, jspWildCard, resourceOnly); //通配符wrapper集合 MappedWrapper[] oldWrappers = context.wildcardWrappers; MappedWrapper[] newWrappers = new MappedWrapper[oldWrappers.length + 1]; if (insertMap(oldWrappers, newWrappers, newWrapper)) { context.wildcardWrappers = newWrappers; int slashCount = slashCount(newWrapper.name); if (slashCount > context.nesting) { context.nesting = slashCount; } } } else if (path.startsWith("*.")) { // Extension wrapper String name = path.substring(2); MappedWrapper newWrapper = new MappedWrapper(name, wrapper, jspWildCard, resourceOnly); //扩展名wrapper MappedWrapper[] oldWrappers = context.extensionWrappers; MappedWrapper[] newWrappers = new MappedWrapper[oldWrappers.length + 1]; if (insertMap(oldWrappers, newWrappers, newWrapper)) { context.extensionWrappers = newWrappers; } } else if (path.equals("/")) { // Default wrapper MappedWrapper newWrapper = new MappedWrapper("", wrapper, jspWildCard, resourceOnly); context.defaultWrapper = newWrapper; } else { // Exact wrapper final String name; if (path.length() == 0) { // Special case for the Context Root mapping which is // treated as an exact match name = "/"; } else { name = path; } MappedWrapper newWrapper = new MappedWrapper(name, wrapper, jspWildCard, resourceOnly); //精确匹配wrapper MappedWrapper[] oldWrappers = context.exactWrappers; MappedWrapper[] newWrappers = new MappedWrapper[oldWrappers.length + 1]; if (insertMap(oldWrappers, newWrappers, newWrapper)) { context.exactWrappers = newWrappers; } } } }
分类:
tomcat
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?