Tomcat中关于Servlet映射器Mapper的实现

来源:互联网 发布:建筑规范数据 编辑:程序博客网 时间:2024/05/16 15:32

Tomcat中对于每个请求的所对于的资源(Host,Context,Wrapper)有一个映射器来实现的

Mapper中映射当前请求url所对应的Wrapper(Servlet)

    private final void internalMapWrapper(ContextVersion contextVersion,                                          CharChunk path,                                          MappingData mappingData)        throws Exception {        int pathOffset = path.getOffset();        int pathEnd = path.getEnd();        int servletPath = pathOffset;        boolean noServletPath = false;        int length = contextVersion.path.length();        if (length != (pathEnd - pathOffset)) {            servletPath = pathOffset + length;        } else {            noServletPath = true;            path.append('/');            pathOffset = path.getOffset();            pathEnd = path.getEnd();            servletPath = pathOffset+length;        }        path.setOffset(servletPath);        // Rule 1 -- Exact Match        Wrapper[] exactWrappers = contextVersion.exactWrappers;        internalMapExactWrapper(exactWrappers, path, mappingData);        // Rule 2 -- Prefix Match        boolean checkJspWelcomeFiles = false;        Wrapper[] 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) {            // The path is empty, redirect to "/"            mappingData.redirectPath.setChars                (path.getBuffer(), pathOffset, pathEnd-pathOffset);            path.setEnd(pathEnd - 1);            return;        }        // Rule 3 -- Extension Match        Wrapper[] 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) {                        Object file = null;                        String pathStr = path.toString();                        try {                            file = contextVersion.resources.lookup(pathStr);                        } catch(NamingException nex) {                            // Swallow not found, since this is normal                        }                        if (file != null && !(file instanceof DirContext) ) {                            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());            }            // Redirection to a folder            char[] buf = path.getBuffer();            if (contextVersion.resources != null && buf[pathEnd -1 ] != '/') {                Object file = null;                String pathStr = path.toString();                try {                    file = contextVersion.resources.lookup(pathStr);                } catch(NamingException nex) {                    // Swallow, since someone else handles the 404                }                if (file != null && file instanceof DirContext) {                    // 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);    }
// 再来看下Mapper中的信息是如何添加的,是在Connector启动时,会去启动MapperListener,会向Mapper注册已经启动的组件(Host,Context,Wrapper)
protected void addWrapper(ContextVersion context, String path,            Object wrapper, boolean jspWildCard, boolean resourceOnly) {         synchronized (context) {            Wrapper newWrapper = new Wrapper();            newWrapper.object = wrapper;            newWrapper.jspWildCard = jspWildCard;            newWrapper.resourceOnly = resourceOnly;            if (path.endsWith("/*")) {                // Wildcard wrapper                newWrapper.name = path.substring(0, path.length() - 2);                Wrapper[] oldWrappers = context.wildcardWrappers;                Wrapper[] newWrappers =                    new Wrapper[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                newWrapper.name = path.substring(2);                Wrapper[] oldWrappers = context.extensionWrappers;                Wrapper[] newWrappers =                    new Wrapper[oldWrappers.length + 1];                if (insertMap(oldWrappers, newWrappers, newWrapper)) {                    context.extensionWrappers = newWrappers;                }            } else if (path.equals("/")) {                // Default wrapper                newWrapper.name = "";                context.defaultWrapper = newWrapper;            } else {                // Exact wrapper                newWrapper.name = path;                Wrapper[] oldWrappers = context.exactWrappers;                Wrapper[] newWrappers =                    new Wrapper[oldWrappers.length + 1];                if (insertMap(oldWrappers, newWrappers, newWrapper)) {                    context.exactWrappers = newWrappers;                }            }        }    }


原创粉丝点击