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

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);

                }

           }

       } 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请求关系类图:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值