Tomcat是怎样根据路径找到对应的Servlet的

本文详细探讨了Tomcat如何在启动时将Host和Context加入到映射中,以及在请求处理过程中,Tomcat如何进行路径匹配,包括精确匹配、通配符匹配、扩展名匹配和默认Servlet的使用。解析了Tomcat内部的Mapper结构和匹配规则,揭示了请求处理的优先级顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

tomcat是怎样找到servlet的?

(1)首先我们来看一下tomcat是怎样把路径加入到mapper中的
①tomcat在启动的时候会注册Host,这个时候mapper会把Host加入到MappedHost中 Mpper#registerHost()

/**
     * Register host.
     */
    private void registerHost(Host host) {
   

        String[] aliases = host.findAliases();
        //添加Host到Mapper中
        mapper.addHost(host.getName(), aliases, host);
		//这个方法主要把context添加到host中
        for (Container container : host.findChildren()) {
   
            if (container.getState().isAvailable()) {
   
            	//这个方法主要是把Contex添加到
                registerContext((Context) container);
            }
        }
        if(log.isDebugEnabled()) {
   
            log.debug(sm.getString("mapperListener.registerHost",
                    host.getName(), domain, service));
        }
    }

这个方法其实是把host加入到其中的一个数组中去,mapper中有一个MappedHost[]

volatile MappedHost[] hosts = new MappedHost[0];
/**
     * Add a new host to the mapper.
     *
     * @param name Virtual host name
     * @param aliases Alias names for the virtual host
     * @param host Host object
     */
    public synchronized void addHost(String name, String[] aliases,
                                     Host host) {
   
        //修改通配符名字,去掉以*.开头的host名字
        name = renameWildcardHost(name);
        //创建一个新的数组装这个host
        MappedHost[] newHosts = new MappedHost[hosts.length + 1];
        //封装这个新的host
        MappedHost newHost = new MappedHost(name, host);
        //将host添加至 MappedHost[] hosts中,如果是重名的话会返回失败,如果是可以插入的话则按照顺序插入
        if (insertMap(hosts, newHosts, newHost)) {
   
            hosts = newHosts;
            //如果新的主机的名字是localhost的话,把新的主机赋值给默认主机
            if (newHost.name.equals(defaultHostName)) {
   
                defaultHost = newHost;
            }
            if (log.isDebugEnabled()) {
   
                log.debug(sm.getString("mapper.addHost.success", name));
            }
        } else {
   
        	//如果是重复的话,则把重复的主机赋值给新的主机
            MappedHost duplicate = hosts[find(hosts, name)];
            if (duplicate.object == host) {
   
                // The host is already registered in the mapper.
                // E.g. it might have been added by addContextVersion()
                if (log.isDebugEnabled()) {
   
                    log.debug(sm.getString("mapper.addHost.sameHost", name));
                }
                newHost = duplicate;
            } else {
   
                log.error(sm.getString("mapper.duplicateHost", name,
                        duplicate.getRealHostName()));
                // Do not add aliases, as removeHost(hostName) won't be able to
                // remove them
                return;
            }
        }
        //如果存在别名的话,则对主机进行别名设置
        List<MappedHost> newAliases = new ArrayList<>(aliases.length);
        for (String alias : aliases) {
   
            alias = renameWildcardHost(alias);
            MappedHost newAlias = new MappedHost(alias, newHost);
            if (addHostAliasImpl(newAlias)) {
   
                newAliases.add(newAlias);
            }
        }
        newHost.addAliases(newAliases);
    }

上面这个方法主要是把host添加到MappedHost[]

registerContext((Context) container);将context添加到host中

 /**
     * Register context.
     */
    private void registerContext(Context context) {
   

        String contextPath = context.getPath();
        if ("/".equals(contextPath)) {
   
            contextPath = "";
        }
        Host host = (Host)context.getParent();

        WebResourceRoot resources = context.getResources();
        //设置欢迎页面数组
        String[] welcomeFiles = context.findWelcomeFiles();
        //创建一个wrapper数组
        List<WrapperMappingInfo> wrappers = new ArrayList<>();
		//这个方法主要是把wrapper添加到context
        for (Container container : context.findChildren()) {
   
        	//这个方法主要是把wrapper包装成WrapperMappingInfo,然后装入到List<WrapperMappingInfo>中
            prepareWrapperMappingInfo(context, (Wrapper) container, wrappers);

            if
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值