`
haitaoandroid
  • 浏览: 26521 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Tomcat源码分析(五)--容器处理连接之servlet的映射

 
阅读更多

本文所要解决的问题:一个http请求过来,容器是怎么知道选择哪个具体servlet?

我们知道,一个Context容器表示一个web应用,一个Wrapper容器表示一个servlet,所以上面的问题可以转换为怎么由Context容器选择servlet,答案是映射器。映射器是实现了Mapper接口的类,作用就是根据请求连接(主要是协议和路径)来选择下一个容器,可以看做是一个哈希表,根据关键字段来选择具体的值,Mapper接口的定义为:

 

public interface Mapper {
    public Container getContainer();//返回与该映射器相关联的容器
    public void setContainer(Container container);
    public String getProtocol();//返回与该映射器处理的协议
    public void setProtocol(String protocol);
    public Container map(Request request, boolean update); //映射函数,实现该函数
}

 

Tomcat源码分析(四)--容器处理链接之责任链模式中已经知道,请求连接到达StandardContext容器的invoke方法,最终会到达StandardContextValue阀的invoke方法里面,在这个invoke方法中有一句这样的代码

 wrapper = (Wrapper) context.map(request, true);

这句代码表示容器会调用map方法来映射请求到具体的wrapper上,意思就是说,根据连接请求request来选择wrapper。上面的map会调用父类ContainerBase的map方法来找到具体的映射器,至于这个映射器和容器是怎么关联上的,具体请参考 Tomcat源码分析(三)--连接器是如何与容器关联的?这篇文章,大致原理是一样的。StandardContext容器有一个标准的映射器实现类StandardContextMapper,所以最终会调用到映射器StandardContextMapper的map方法,这个方法是选择servlet的关键(省略了一些代码):

 

 

 public Container map(Request request, boolean update) {
  // Identify the context-relative URI to be mapped
        String contextPath =
            ((HttpServletRequest) request.getRequest()).getContextPath();
        String requestURI = ((HttpRequest) request).getDecodedRequestURI();
        String relativeURI = requestURI.substring(contextPath.length());
        // Apply the standard request URI mapping rules from the specification
        Wrapper wrapper = null;
        String servletPath = relativeURI;
        String pathInfo = null;
        String name = null;

        // Rule 1 -- Exact Match
        if (wrapper == null) {
            if (debug >= 2)
                context.log("  Trying exact match");
            if (!(relativeURI.equals("/")))
                name = context.findServletMapping(relativeURI);
            if (name != null)
                wrapper = (Wrapper) context.findChild(name);
            if (wrapper != null) {
                servletPath = relativeURI;
                pathInfo = null;
            }
        }

        // Rule 2 -- Prefix Match
        if (wrapper == null) {
            if (debug >= 2)
                context.log("  Trying prefix match");
            servletPath = relativeURI;
            while (true) {
                name = context.findServletMapping(servletPath + "/*");
                if (name != null)
                    wrapper = (Wrapper) context.findChild(name);
                if (wrapper != null) {
                    pathInfo = relativeURI.substring(servletPath.length());
                    if (pathInfo.length() == 0)
                        pathInfo = null;
                    break;
                }
                int slash = servletPath.lastIndexOf('/');
                if (slash < 0)
                    break;
                servletPath = servletPath.substring(0, slash);
            }
        }

        // Rule 3 -- Extension Match
        if (wrapper == null) {
            if (debug >= 2)
                context.log("  Trying extension match");
            int slash = relativeURI.lastIndexOf('/');
            if (slash >= 0) {
                String last = relativeURI.substring(slash);
                int period = last.lastIndexOf('.');
                if (period >= 0) {
                    String pattern = "*" + last.substring(period);
                    name = context.findServletMapping(pattern);
                    if (name != null)
                        wrapper = (Wrapper) context.findChild(name);
                    if (wrapper != null) {
                        servletPath = relativeURI;
                        pathInfo = null;
                    }
                }
            }
        }

        // Rule 4 -- Default Match
        if (wrapper == null) {
            if (debug >= 2)
                context.log("  Trying default match");
            name = context.findServletMapping("/");
            if (name != null)
                wrapper = (Wrapper) context.findChild(name);
            if (wrapper != null) {
                servletPath = relativeURI;
                pathInfo = null;
            }
        }
}


代码很长,但是很容易看懂,就是分4中匹配模式(完全匹配,前缀匹配,扩展匹配,默认匹配)来选择wrapper,关键代码就是name = context.findServletMapping和wrapper = (Wrapper) context.findChild(name);这里面context都是StandardContext。context.findServletMapping是根据匹配模式来找到servlet名字,context.findChild是根据servlet名字找到具体的wrapper。findServletMapping方法很简单,就是在一个HashMap里面得到servlet名字,代码如下,其中servletMappings是一个HashMap:

 

 

    public String findServletMapping(String pattern) {
        synchronized (servletMappings) {
            return ((String) servletMappings.get(pattern));
        }
    }


findChild方法跟findServletMapping方法一样,也是在一个HashMap找wrapper容器。至此,已经能够回答一开始的问题了,StandardContext容器根据映射器来选择wrapper。当然,容器Engine和Host也是根据映射器来选择它们的下一级容器的。

分享到:
评论

相关推荐

    JAVA上百实例源码以及开源项目源代码

    Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...

    JAVA上百实例源码以及开源项目

    笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对IT的憧憬、向往!此时此...

    《程序天下:J2EE整合详解与典型案例》光盘源码

    2.3.2 使用MVC模式的不足之处 2.4 目前市场上常见的轻量级J2EE开发容器 2.5 小结 第二篇 建立和使用J2EE的开发平台 第三章 建立Java的开发平台 3.1 建立Java的开发环境 3.1.1 下载JDK 3.1.2 安装JDK 3.1.3 设定Path...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (2)

    一共四个,其中pdf 三个包,源码一个包 第一章 J2EE快速入门 1.1 J2EE概述 1.1.1 J2EE的来源 1.1.2 J2EE整体框架 1.1.3 从J2EE到JavaEE 1.2 J2EE组件 1.2.1 客户端组件 1.2.2 Web组件 1.2.3 业务逻辑组件 1.3 J2EE...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    一共四个,其中pdf 三个包,源码一个包 第一章 J2EE快速入门 1.1 J2EE概述 1.1.1 J2EE的来源 1.1.2 J2EE整体框架 1.1.3 从J2EE到JavaEE 1.2 J2EE组件 1.2.1 客户端组件 1.2.2 Web组件 1.2.3 业务逻辑组件 1.3 J2EE...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    一共四个,其中pdf 三个包,源码一个包 第一章 J2EE快速入门 1.1 J2EE概述 1.1.1 J2EE的来源 1.1.2 J2EE整体框架 1.1.3 从J2EE到JavaEE 1.2 J2EE组件 1.2.1 客户端组件 1.2.2 Web组件 1.2.3 业务逻辑组件 1.3 J2EE...

    java开源包8

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包4

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    外文翻译 stus MVC

    ActionServlet is the Command part of the MVC implementation and is the core of the Framework. ActionServlet (Command) creates and uses Action, an ActionForm, and ActionForward. As mentioned earlier, ...

    java开源包1

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包10

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包11

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包2

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包3

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包6

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包5

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包7

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包9

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包101

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

Global site tag (gtag.js) - Google Analytics