您的位置:首页 > 运维架构 > Tomcat

tomcat源码研读笔记—tomcat的接收请求之四 StandardContext接收请求

2018-03-22 08:54 573 查看
StandardContext继承关系:



根据继承关系,我们可以知道,跟之前处理请求的机制基本是一致的。只是standardContext重写了父类的invoke方法:
 public void invoke(Request request, Response response)
       throws IOException, ServletException {
 
       // Wait if we are reloading
       while (getPaused()) {
           try {
                Thread.sleep(1000);
           } catch (InterruptedException e) {
                ;
           }
       }
 
       // Normal request processing
       if (swallowOutput) {
           try {
               SystemLogHandler.startCapture();
                super.invoke(request,response);
           } finally {
                String log =SystemLogHandler.stopCapture();
                if (log != null &&log.length() > 0) {
                    log(log);
       
4000
         }
           }
       } else {
           super.invoke(request, response);
       }
 
}
 
单它并没有做什么其他过多的逻辑,然后又将操作提交给了父类的invoke方法,那么又再次进入我们之前处理的流程:
 
1,  调用了ContainerBase中的Invoke方法
2,  进而掉用了valve的invoke方法,而这里实现了valve接口的实现类是StandardContextValve
3,  这个时候将会调用StandardContextValve的invoke方法了
    public void invoke(Request request, Responseresponse,
                       ValveContextvalveContext)
        throws IOException, ServletException {
 
        // Validate the request and responseobject types
        if (!(request.getRequest() instanceofHttpServletRequest) ||
            !(response.getResponse() instanceofHttpServletResponse)) {
            return;     // NOTE - Not much else we can dogenerically
        }
 
        // Disallow any direct access toresources under WEB-INF or META-INF
       HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
        String contextPath =hreq.getContextPath();
        String requestURI = ((HttpRequest)request).getDecodedRequestURI();
        String relativeURI =
            requestURI.substring(contextPath.length()).toUpperCase();
        if(relativeURI.equals("/META-INF") ||
           relativeURI.equals("/WEB-INF") ||
           relativeURI.startsWith("/META-INF/") ||
           relativeURI.startsWith("/WEB-INF/")) {
            notFound(requestURI,(HttpServletResponse) response.getResponse());
            return;
        }
 
        Context context = (Context)getContainer();
 
        // Select the Wrapper to be used forthis Request
        Wrapper wrapper = null;
        try {
            wrapper = (Wrapper)context.map(request, true);
        } catch (IllegalArgumentException e) {
            badRequest(requestURI,
                       (HttpServletResponse)response.getResponse());
            return;
        }
        if (wrapper == null) {
            notFound(requestURI,(HttpServletResponse) response.getResponse());
            return;
        }
 
        // Ask this Wrapper to process thisRequest
        response.setContext(context);
 
        wrapper.invoke(request, response);
 
}
 
根据代码我们可以知道,将会调用StandardContextMapper的map方法来获取对应的wrapper
 
4,  StandardContextMapper的map方法
  public Container map(Request request, booleanupdate) {
 
 
        int debug = context.getDebug();
 
        // Has this request already beenmapped?
        if (update &&(request.getWrapper() != null))
            return (request.getWrapper());
 
        // Identify the context-relative URI tobe mapped
        String contextPath =
            ((HttpServletRequest)request.getRequest()).getContextPath();
        String requestURI = ((HttpRequest)request).getDecodedRequestURI();
        String relativeURI =requestURI.substring(contextPath.length());
 
 
        if (debug >= 1)
            context.log("MappingcontextPath='" + contextPath +
                        "' with requestURI='" +requestURI +
                        "' andrelativeURI='" + relativeURI + "'");
 
        // Apply the standard request URImapping 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;
            }
        }
 
        // Update the Request (if requested)and return this Wrapper
        if ((debug >= 1) && (wrapper!= null))
            context.log(" Mapped to servlet'" + wrapper.getName() +
                        "' with servletpath '" + servletPath +
                        "' and path info'" + pathInfo +
                        "' andupdate=" + update);
        if (update) {
            request.setWrapper(wrapper);
            ((HttpRequest)request).setServletPath(servletPath);
            ((HttpRequest)request).setPathInfo(pathInfo);
        }
        return (wrapper);
 
}
我们这里只需要知道根据请求的url逻辑进行匹配获取对应的封装好实现了warpper的StandardWrapper
 
6,然后调用standardWrapper的invoke方法

 StandardContex请求流程图:



standardContext请求关系类图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: