• request获取容器过程


    
    获取容器过程
    
    CoyoteAdapter.postParseRequest(org.apache.coyote.Request req, Request request,
                org.apache.coyote.Response res, Response response)
    
    connector.getService().getMapper().map(serverName, decodedURI,
                        version, request.getMappingData());
    
    Mapper.map
    
    public void map(MessageBytes host, MessageBytes uri, String version,
                        MappingData mappingData) throws IOException {
    
            if (host.isNull()) {
                host.getCharChunk().append(defaultHostName);
            }
            host.toChars();
            uri.toChars();
            internalMap(host.getCharChunk(), uri.getCharChunk(), version,
                    mappingData);
        }
    
    Mapper.internalMap
    
     private final void internalMap(CharChunk host, CharChunk uri,
                String version, MappingData mappingData) throws IOException {
    
            if (mappingData.host != null) {
                // The legacy code (dating down at least to Tomcat 4.1) just
                // skipped all mapping work in this case. That behaviour has a risk
                // of returning an inconsistent result.
                // I do not see a valid use case for it.
                throw new AssertionError();
            }
    
            uri.setLimit(-1);
            // Virtual host mapping
            MappedHost[] hosts = this.hosts;
    //根据host域名精确查找host
            MappedHost mappedHost = exactFindIgnoreCase(hosts, host);
            if (mappedHost == null) {
                // Note: Internally, the Mapper does not use the leading * on a
                //       wildcard host. This is to allow this shortcut.
    //*.apache.org --> .apache.org,通过这个去查找
                int firstDot = host.indexOf('.');
                if (firstDot > -1) {
                    int offset = host.getOffset();
                    try {
                        host.setOffset(firstDot + offset);
                        mappedHost = exactFindIgnoreCase(hosts, host);
                    } finally {
                        // Make absolutely sure this gets reset
                        host.setOffset(offset);
                    }
                }
                if (mappedHost == null) {
                    mappedHost = defaultHost;//如果没有找到就使用默认host
                    if (mappedHost == null) {
                        return;
                    }
                }
            }
            mappingData.host = mappedHost.object;
    
            // Context mapping 前缀匹配
            ContextList contextList = mappedHost.contextList;
            MappedContext[] contexts = contextList.contexts;
            int pos = find(contexts, uri);
            if (pos == -1) {
                return;
            }
    
            int lastSlash = -1;
            int uriEnd = uri.getEnd();
            int length = -1;
            boolean found = false;
            MappedContext context = null;
            while (pos >= 0) {
                context = contexts[pos];
                if (uri.startsWith(context.name)) {
    //如果长度一样直接表示找到匹配的对象
                    length = context.name.length();
                    if (uri.getLength() == length) {
                        found = true;
                        break;
                    } else if (uri.startsWithIgnoreCase("/", length)) {
                        found = true;
                        break;
                    }
                }
    //查找最后一个/的位置(匹配最长的路径),然后从开始到这个点进行匹配
                if (lastSlash == -1) {
                    lastSlash = nthSlash(uri, contextList.nesting + 1);
                } else {
                    lastSlash = lastSlash(uri);
                }
                uri.setEnd(lastSlash);
                pos = find(contexts, uri);
            }
            uri.setEnd(uriEnd);
    
            if (!found) {
    //如果没有找打,使用默认的context,如果连默认的都没有直接返回null
                if (contexts[0].name.equals("")) {
                    context = contexts[0];
                } else {
                    context = null;
                }
            }
            if (context == null) {
                return;
            }
    
            mappingData.contextPath.setString(context.name);
    
            ContextVersion contextVersion = null;
            ContextVersion[] contextVersions = context.versions;
            final int versionCount = contextVersions.length;
            if (versionCount > 1) {
                Context[] contextObjects = new Context[contextVersions.length];
                for (int i = 0; i < contextObjects.length; i++) {
                    contextObjects[i] = contextVersions[i].object;
                }
                mappingData.contexts = contextObjects;
                if (version != null) {
    //精确查找版本
                    contextVersion = exactFind(contextVersions, version);
                }
            }
            if (contextVersion == null) {
                // Return the latest version
                // The versions array is known to contain at least one element
                contextVersion = contextVersions[versionCount - 1];
            }
            mappingData.context = contextVersion.object;
            mappingData.contextSlashCount = contextVersion.slashCount;
    
            // Wrapper mapping
            if (!contextVersion.isPaused()) {
                internalMapWrapper(contextVersion, uri, mappingData);
            }
    
        }
    
    
    Mapper.internalMapWrapper
    
    
    private final void internalMapWrapper(ContextVersion contextVersion,
                                              CharChunk path,
                                              MappingData mappingData) throws IOException {
    
            int pathOffset = path.getOffset();
            int pathEnd = path.getEnd();
            boolean noServletPath = false;
    
            int length = contextVersion.path.length();
            if (length == (pathEnd - pathOffset)) {
                noServletPath = true;//如果请求路径和context路径一样长,那么就表示没有servletPath,这种路径一般是使用默认的index页面
            }
            int servletPath = pathOffset + length;
            path.setOffset(servletPath);//设置servlet路径,比如localhost:8080/test/index --> servlet路径为index,那么偏移地址为index第一个字符的下标
    
            // Rule 1 -- Exact Match 精确匹配
            MappedWrapper[] exactWrappers = contextVersion.exactWrappers;
            internalMapExactWrapper(exactWrappers, path, mappingData);
    
            // Rule 2 -- Prefix Match 前缀匹配,这里的匹配和context的匹配方式一样
            boolean checkJspWelcomeFiles = false;
            MappedWrapper[] wildcardWrappers = contextVersion.wildcardWrappers;
            if (mappingData.wrapper == null) {
                internalMapWildcardWrapper(wildcardWrappers, contextVersion.nesting,
                                           path, mappingData);
                if (mappingData.wrapper != null && mappingData.jspWildCard) {
                    char[] buf = path.getBuffer();
                    if (buf[pathEnd - 1] == '/') {
                        /*
                         * Path ending in '/' was mapped to JSP servlet based on
                         * wildcard match (e.g., as specified in url-pattern of a
                         * jsp-property-group.
                         * Force the context's welcome files, which are interpreted
                         * as JSP files (since they match the url-pattern), to be
                         * considered. See Bugzilla 27664.
                         */
                        mappingData.wrapper = null;
                        checkJspWelcomeFiles = true;
                    } else {
                        // See Bugzilla 27704
                        mappingData.wrapperPath.setChars(buf, path.getStart(),
                                                         path.getLength());
                        mappingData.pathInfo.recycle();
                    }
                }
            }
    
            if(mappingData.wrapper == null && noServletPath &&
                    contextVersion.object.getMapperContextRootRedirectEnabled()) {
                // The path is empty, redirect to "/"
                path.append('/');
                pathEnd = path.getEnd();
                mappingData.redirectPath.setChars
                    (path.getBuffer(), pathOffset, pathEnd - pathOffset);
                path.setEnd(pathEnd - 1);
                return;
            }
    
            // Rule 3 -- Extension Match
            MappedWrapper[] extensionWrappers = contextVersion.extensionWrappers;
            if (mappingData.wrapper == null && !checkJspWelcomeFiles) {
                internalMapExtensionWrapper(extensionWrappers, path, mappingData,
                        true);
            }
    
            // Rule 4 -- Welcome resources processing for servlets
            if (mappingData.wrapper == null) {
                boolean checkWelcomeFiles = checkJspWelcomeFiles;
                if (!checkWelcomeFiles) {
                    char[] buf = path.getBuffer();
                    checkWelcomeFiles = (buf[pathEnd - 1] == '/');
                }
                if (checkWelcomeFiles) {
                    for (int i = 0; (i < contextVersion.welcomeResources.length)
                             && (mappingData.wrapper == null); i++) {
                        path.setOffset(pathOffset);
                        path.setEnd(pathEnd);
                        path.append(contextVersion.welcomeResources[i], 0,
                                contextVersion.welcomeResources[i].length());
                        path.setOffset(servletPath);
    
                        // Rule 4a -- Welcome resources processing for exact macth
                        internalMapExactWrapper(exactWrappers, path, mappingData);
    
                        // Rule 4b -- Welcome resources processing for prefix match
                        if (mappingData.wrapper == null) {
                            internalMapWildcardWrapper
                                (wildcardWrappers, contextVersion.nesting,
                                 path, mappingData);
                        }
    
                        // Rule 4c -- Welcome resources processing
                        //            for physical folder
                        if (mappingData.wrapper == null
                            && contextVersion.resources != null) {
                            String pathStr = path.toString();
                            WebResource file =
                                    contextVersion.resources.getResource(pathStr);
                            if (file != null && file.isFile()) {
                                internalMapExtensionWrapper(extensionWrappers, path,
                                                            mappingData, true);
                                if (mappingData.wrapper == null
                                    && contextVersion.defaultWrapper != null) {
                                    mappingData.wrapper =
                                        contextVersion.defaultWrapper.object;
                                    mappingData.requestPath.setChars
                                        (path.getBuffer(), path.getStart(),
                                         path.getLength());
                                    mappingData.wrapperPath.setChars
                                        (path.getBuffer(), path.getStart(),
                                         path.getLength());
                                    mappingData.requestPath.setString(pathStr);
                                    mappingData.wrapperPath.setString(pathStr);
                                }
                            }
                        }
                    }
    
                    path.setOffset(servletPath);
                    path.setEnd(pathEnd);
                }
    
            }
    
            /* welcome file processing - take 2
             * Now that we have looked for welcome files with a physical
             * backing, now look for an extension mapping listed
             * but may not have a physical backing to it. This is for
             * the case of index.jsf, index.do, etc.
             * A watered down version of rule 4
             */
            if (mappingData.wrapper == null) {
                boolean checkWelcomeFiles = checkJspWelcomeFiles;
                if (!checkWelcomeFiles) {
                    char[] buf = path.getBuffer();
                    checkWelcomeFiles = (buf[pathEnd - 1] == '/');
                }
                if (checkWelcomeFiles) {
                    for (int i = 0; (i < contextVersion.welcomeResources.length)
                             && (mappingData.wrapper == null); i++) {
                        path.setOffset(pathOffset);
                        path.setEnd(pathEnd);
                        path.append(contextVersion.welcomeResources[i], 0,
                                    contextVersion.welcomeResources[i].length());
                        path.setOffset(servletPath);
                        internalMapExtensionWrapper(extensionWrappers, path,
                                                    mappingData, false);
                    }
    
                    path.setOffset(servletPath);
                    path.setEnd(pathEnd);
                }
            }
    
    
            // Rule 7 -- Default servlet
            if (mappingData.wrapper == null && !checkJspWelcomeFiles) {
                if (contextVersion.defaultWrapper != null) {
                    mappingData.wrapper = contextVersion.defaultWrapper.object;
                    mappingData.requestPath.setChars
                        (path.getBuffer(), path.getStart(), path.getLength());
                    mappingData.wrapperPath.setChars
                        (path.getBuffer(), path.getStart(), path.getLength());
                    mappingData.matchType = MappingMatch.DEFAULT;
                }
                // Redirection to a folder
                char[] buf = path.getBuffer();
                if (contextVersion.resources != null && buf[pathEnd -1 ] != '/') {
                    String pathStr = path.toString();
                    WebResource file;
                    // Handle context root
                    if (pathStr.length() == 0) {
                        file = contextVersion.resources.getResource("/");
                    } else {
                        file = contextVersion.resources.getResource(pathStr);
                    }
                    if (file != null && file.isDirectory() &&
                            contextVersion.object.getMapperDirectoryRedirectEnabled()) {
                        // Note: this mutates the path: do not do any processing
                        // after this (since we set the redirectPath, there
                        // shouldn't be any)
                        path.setOffset(pathOffset);
                        path.append('/');
                        mappingData.redirectPath.setChars
                            (path.getBuffer(), path.getStart(), path.getLength());
                    } else {
                        mappingData.requestPath.setString(pathStr);
                        mappingData.wrapperPath.setString(pathStr);
                    }
                }
            }
    
            path.setOffset(pathOffset);
            path.setEnd(pathEnd);
        }
  • 相关阅读:
    懒懒的~~
    BigDecimal,注解
    遇到的一点问题些
    npm一点点
    TortoiseSvn问题研究(一)
    关于maven-基本
    HttpServletRequest二三事
    学习迭代1需求分析
    FMDB简单使用
    计算机中的事务、回滚
  • 原文地址:https://www.cnblogs.com/honger/p/10363078.html
Copyright © 2020-2023  润新知