tomcat源码分析五:Mapper(url到Wrapper的映射)

前面提到,tomcat从架构上看,包含Service,Engine,Host,Context,Wrapper。那么,当用户发起一个请求时,tomcat是如何将url映射到具体的Wrapper上的呢,就这是本文要阐述的问题。

与url到Wrapper映射相关的类位于org.apache.catalina.mapper包下,包含四个类:

  • Mapper:映射关系最核心的、最重要的类。完成url与Host,Context,Wrapper映射关系的初始化、变更、存储及映射
  • MapperListener:实现了ContainerListenerLifecycleListener接口,监听tomcat组件的变化,当有Host,Context及Wrapper变更时,调用Mapper相关方法,增加或者删除Host,Context,Wrapper等。
  • MappingData:url映射后的数据,表示一个url具体映射到哪个host,哪个context,哪个wrapper上。
  • WrapperMappingInfo:表示一个Wrapper的信息,是一个普通的类,不太重要。

本文章主要介绍Mapper,对其中用到的MapperingData做简要介绍。

Mapper主要功能是完成url到Wrapper的映射,有三个主要的功能
1. 映射关系存储:存储所有的Host,context及Wrapper的对应关系;
2. 映射关系初始化及变更:当新增一个组件或者移除一个组件时,mapper如何维护url到Wrapper的映射关系;
3. 映射关系使用:根据url,映射到具体的host,context和wrapper。

映射关系存储

我们先上结论,再看详细的代码。

总体结论

我们知道,一个Service有一个Engine,而一个Engine中有一个Mapper。根据Engine,Host,Context及Wrapper的对应关系,易得到以下的结论。

  • 一个Mapper中,应该保存有多个Host对象(的确是这样的,每个Host对象称之为MappedHost,多个MappedHost以数组形式组合,各元素通过其name进行排序)
  • 一个Host对象包含多个context(Context在Mapper中定义为MappedContext,也是通过数组形式存在,并且元素根据MappedContext的命名排序。但是与组件不同的是,每一个Context可以有多个版本,因此每一个MappedContext 包含了多个ContextVersion,每一个MappedContext下的多个ContextVersion表示同一个Context的多个版本
  • 一个Context包含多个Wrapper(此处的Context在Mapper中为ContextVersion,包含多个Wrapper,这些Wrapper分成四类,精确匹配的Wrapper,前缀匹配的Wrapper,扩展名匹配的Wrapper,默认的Wrapper,在Mapper中,每一个Wrapper都通过一个MappedWrapper表示)
    因此,Mapper的构成可以用下图表示
    这里写图片描述

详细代码

辅助类MapElement

个人感觉这个名字起的不太好,让人以为是Map,其实就是一个含有名字的Object。

protected abstract static class MapElement<T> {
   
        public final String name;
        public final T object;

        public MapElement(String name, T object) {
            this.name = name;
            this.object = object;
        }
    }

mapper 的属性

    //定义所有的Host组合,表示一个Engine下所有Host
    volatile MappedHost[] hosts = new MappedHost[0];
    /**
     * Default host name.
     */
    private String defaultHostName = null;
    private volatile MappedHost defaultHost = null;

    /**
     * Mapping from Context object to Context version to support
     * RequestDispatcher mappings.
     */
     // 没有明白到底干吗用的
    private final Map<Context, ContextVersion> contextObjectToContextVersionMap =
            new ConcurrentHashMap<>();

MappedHost定义

protected static final class MappedHost extends MapElement<Host> {
   

        // 包含的COntext信息,定义的是一个Object,其实内部是一个数组,下面可以看到
        public volatile ContextList contextList;

        /**
         * Link to the "real" MappedHost, shared by all aliases.
         * 因为一个Host,可能是真正的一个Host,也可能只是起、一个别名,而在Mapper中,两者都是MapperHost,
         * 只是真正的MapperHost的realHost是自身,而alias的MapperHost的realHost是其对应的真实的MapperHost
         */
        private final MappedHost realHost;

        /**
        * 所有注册的别名的MapperHost
        * 对于alias MapperHost,这个值为null。当一个 real MapperHost 没有alias的时候,这个值也为空
        */
        private final List<MappedHost> aliases;
    }

ContextList 定义

    protected static final class ContextList {
   

        // 如在MappedHost定义中提到的,这个里面存储的是一系列的MapperContext
        public final MappedContext[] contexts;
        // 这个值主要是为了 url 到wrapper的映射时更快的定位目标,在看代码时可以忽略
        public final int nesting;
    }

MappedContext定义

    protected static final class MappedContext extends MapElement<Void> {
   
        // 一个MappedContext 中又有多个ContextVersion,表示多个版本的context
        public volatile ContextVersion[] versions;
    }

ContextVersion的定义

    protected static final class ContextVersion extends MapElement<Context> {
           
        // context 的匹配路径
        public final String path;
        // 没有直接的用处,主要目的是为了计算Context中的nesting
        public final int slashCount;
        public final WebResourceRoot resources;
        //context 的欢迎页面
        public String[] welcomeResources;
        // 默认的wrapper
        public MappedWrapper defaultWrapper = null;
        // 精确匹配路径的 wrapper
        public MappedWrapper[] exactWrappers = new MappedWrapper[0];
        // 通配符结束的wrapper
        public MappedWrapper[] wildcardWrappers = new MappedWrapper[0];
        // 扩展名匹配的wrapper
        public MappedWrapper[] extensionWrappers = new MappedWrapper[0];
        public int nesting = 0;
        // 这个context是否还可用,是否被暂停
        private volatile boolean paused;
    }

MappedWrapper 定义

仅有两个属性

    protected static class MappedWrapper extends MapElement<Wrapper> {
   
        // true if the wrapper corresponds to the JspServlet and the mapping path contains a wildcard; false otherwise
        public final boolean jspWildCard;
        //true if this wrapper always expects a physical resource to be present (such as a JSP)
        public final boolean resourceOnly;
    }

小结:

从定义可以看出,Mapper中包含了这个Engine中所有的映射关系,首先包含了多个MapperHost,MapperHost分两类,一个是real MapperHost,另一类是 alias的MapperHost。每一个MapperHost都包含有多个MappedContext,代表不同的Context,每一个MappedContext又有多个ContextVersion,表示每一个Context的不同的版本号,这样在请求参数

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值