0
点赞
收藏
分享

微信扫一扫

彻底理解servlet匹配顺序 / 和 /*的区别

倚然君 2022-03-16 阅读 96

先看一下tomcat是怎么保存servlet的路径的。理解了这个再理解匹配顺序就很简单了。
每个servlet在tomcat中是由一个wrapper表示的,由这个wrapper去进行servlet的加载,执行等操作。所以添加一个servlet到context中就是添加一个wrapper。tomcat根据servlet配置的映射路径把wrapper分成四类。
name表示之后用于匹配的部分。

  1. 以/*结束:Wildcard wrapper。 name是 / *之前的部分
  2. 以*.开始:Extension wrapper 。 name是 *.之后的部分
  3. /:Default wrapper。 name是空字符串
  4. 其余的:Exact wrapper。 如果映射路径为空,把name设为/,其它就是path本身

匹配顺序
匹配servlet的过程就是根据url去匹配上面提到的name的过程。

  1. 匹配exact wrapper。完全匹配。
  2. 匹配Wildcard wrapper。前缀匹配。
  3. 匹配Extension wrapper。后缀名匹配。
  4. 匹配Default wrapper。默认匹配。

这样区分/ 和 /* 就很简单了。 / 会把DispatcherServlet保存成Default wrapper,对应默认匹配,/ * 会把DispatcherServlet保存成Wildcard wrapper,对应前缀匹配。所以如果配成/*,那就是会把所有的请求都匹配到DispatcherServlet中。如果配成/,那就会先匹配tomcat自带的一些servlet,比如一些后缀匹配servlet(.jsp之类的)。

源码部分

添加servlet部分

// org/apache/catalina/mapper/Mapper.java

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);
            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);
            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);
            MappedWrapper[] oldWrappers = context.exactWrappers;
            MappedWrapper[] newWrappers = new MappedWrapper[oldWrappers.length + 1];
            if (insertMap(oldWrappers, newWrappers, newWrapper)) {
                context.exactWrappers = newWrappers;
            }
        }
    }
}

匹配部分
只展示完全匹配的代码
主要是对url为/的特殊处理。

// org/apache/catalina/mapper/Mapper.java
private final void internalMapExactWrapper
(MappedWrapper[] wrappers, CharChunk path, MappingData mappingData) {
    MappedWrapper wrapper = exactFind(wrappers, path);
    if (wrapper != null) {
        mappingData.requestPath.setString(wrapper.name);
        mappingData.wrapper = wrapper.object;
        if (path.equals("/")) {
            // Special handling for Context Root mapped servlet
            mappingData.pathInfo.setString("/");
            mappingData.wrapperPath.setString("");
            // This seems wrong but it is what the spec says...
            mappingData.contextPath.setString("");
        } else {
            mappingData.wrapperPath.setString(wrapper.name);
        }
    }
}
举报

相关推荐

0 条评论