当前位置:web 服务器 > Tomcat >>

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

 本文所要解决的问题:一个http请求过来,容器是怎么知道选择哪个具体servlet?
     我们知道,一个Context容器表示一个web应用,一个Wrapper容器表示一个servlet,所以上面的问题可以转换为怎么由Context容器选择servlet,答案是映射器。映射器是实现了Mapper接口的类,作用就是根据请求连接(主要是协议和路径)来选择下一个容器,可以看做是一个哈希表,根据关键字段来选择具体的值,Mapper接口的定义为:
[java] 
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方法,在StandardContext容器有一句这样的代码:
[java] 
wrapper = (Wrapper) context.map(request, true); 
这句代码表示容器会调用map方法来映射请求到具体的wrapper上,意思就是说,根据连接请求request来选择wrapper。上面的map会调用父类ContainerBase的map方法来找到具体的映射器,至于这个映射器和容器是怎么关联上的,具体请参考 Tomcat源码分析(三)--连接器是如何与容器关联的?这篇文章,大致原理是一样的。StandardContext容器有一个标准的映射器实现类StandardContextMapper,所以最终会调用到映射器StandardContextMapper的map方法,这个方法是选择servlet的关键(省略了一些代码):
[java] 
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 !=

补充:软件开发 , Java ,
Apache
IIS
Nginx
Tomcat
如果你遇到web 服务器难题:
请访问www.zzzyk.com 试试
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,