request获取容器过程
阅读原文时间:2023年07月16日阅读:2

获取容器过程

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);  
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章