您的位置:首页 > 其它

WebX学习二——URL请求流程分析

2015-06-15 20:26 197 查看

URL请求流程分析

1.在index页面中设置了



得到如下链接



当这个get请求发出的时候,流程是这样的:

首先,它被webx中配置的Filter捕获:




进入源码分析发现:该请求进入了WebxFrameworkFilter的doFilter方法:

@Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String path = getResourcePath(request);

        if (isExcluded(path)) {
            log.debug("Excluded request: {}", path);
            chain.doFilter(request, response);
            return;
        } else {
            log.debug("Accepted and started to process request: {}", path);
        }

        try {
            getWebxComponents().getWebxRootController().service(request, response, chain);
        } catch (IOException e) {
            throw e;
        } catch (ServletException e) {
            throw e;
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }








使用getResourcePath(request)得到path,然后通过isExcluded方法进行判断是否不进行处理。

不进行处理的urlPattern在配置中进行了配置。



显然最后返回false,不排除在外,因此webx接管了这个请求url。

之后getWebxComponents.getWebxRootController.service;

getWebxComponents得到配置中配置的所有components。然后获得处理web请求的WebxRootController,执行它的service方法,入参为原始的HttpServletRequest和HttpServletResponse,以及配置中配置的FilterChain.

void service(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws Exception;


然后进入service方法进行请求的分类:

public final void service(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws Exception {
        RequestContext requestContext = null;

        try {
            requestContext = assertNotNull(getRequestContext(request, response), "could not get requestContext");

            // 如果请求已经结束,则不执行进一步的处理。例如,当requestContext已经被重定向了,则立即结束请求的处理。
            if (isRequestFinished(requestContext)) {
                return;
            }

            // 请求未结束,则继续处理...
            request = requestContext.getRequest();
            response = requestContext.getResponse();

            // 如果是一个内部请求,则执行内部请求
            if (handleInternalRequest(request, response)) {
                return;
            }

            // 如果不是内部的请求,并且没有被passthru,则执行handleRequest
            if (isRequestPassedThru(request) || !handleRequest(requestContext)) {
                // 如果请求被passthru,或者handleRequest返回false(即pipeline放弃请求),
                // 则调用filter chain,将控制交还给servlet engine。
                giveUpControl(requestContext, chain);
            }
        } catch (Throwable e) {
            handleException(requestContext, request, response, e);
        } finally {
            commitRequest(requestContext);
        }
    }


其中有
handleInternalRequest
和 处理非内部请求的代码块。

接下来判断是否是内部请求,该方法在是内部请求之后会执行然后返回true:

private boolean handleInternalRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        RequestHandlerContext internalRequestHandlerContext = internalHandlerMapping.getRequestHandlerContext(request, response);

        if (internalRequestHandlerContext == null) {
            return false;
        }

        // 如果是一个内部请求,则执行内部请求
        internalRequestHandlerContext.handleRequest();

        return true;
    }


显然本例中返回了false,意味着它不是内部请求,它是一个外部的通过页面传来的链接。

在判断了既不是paththru的请求也不是内部请求,进入if中的handleRequest(requestContext)




寻找path对应的components。

public WebxComponent findMatchedComponent(String path) {
            if (!path.startsWith("/")) {
                path = "/" + path;
            }

            WebxComponent defaultComponent = getDefaultComponent();
            WebxComponent matched = null;

            // 前缀匹配componentPath。
            for (WebxComponent component : this) {
                if (component == defaultComponent) {
                    continue;
                }

                String componentPath = component.getComponentPath();

                if (!path.startsWith(componentPath)) {
                    continue;
                }

                // path刚好等于componentPath,或者path以componentPath/为前缀
                if (path.length() == componentPath.length() || path.charAt(componentPath.length()) == '/') {
                    matched = component;
                    break;
                }
            }

            // fallback to default component
            if (matched == null) {
                matched = defaultComponent;
            }

            return matched;
        }


在寻找对应的component的时候,如果没有找到,则说明在配置里面没有配对应的component,则选择defaultComponent进行配置。

然后将该component放入request作为参数,再进入service的handle.invoke():

执行invokeNext()

public void invokeNext() {
            assertInitialized();

            if (broken) {
                return;
            }

            try {
                executingIndex++;

                if (executingIndex <= executedIndex) {
                    throw new IllegalStateException(descCurrentValve() + " has already been invoked: "
                                                    + valves[executingIndex]);
                }

                executedIndex++;

                if (executingIndex < valves.length) {
                    Valve valve = valves[executingIndex];

                    try {
                        if (log.isTraceEnabled()) {
                            log.trace("Entering {}: {}", descCurrentValve(), valve);
                        }

                        valve.invoke(this);
                    } catch (PipelineException e) {
                        throw e;
                    } catch (Exception e) {
                        throw new PipelineException("Failed to invoke " + descCurrentValve() + ": " + valve, e);
                    } finally {
                        if (log.isTraceEnabled()) {
                            log.trace("...Exited {}: {}", descCurrentValve(), valve);
                        }
                    }

                    if (executedIndex < valves.length && executedIndex == executingIndex) {
                        if (log.isTraceEnabled()) {
                            log.trace("{} execution was interrupted by {}: {}", new Object[] { descCurrentPipeline(),
                                                                                               descCurrentValve(), valve });
                        }
                    }
                } else {
                    if (log.isTraceEnabled()) {
                        log.trace("{} reaches its end.", descCurrentPipeline());
                    }
                }
            } finally {
                executingIndex--;
            }
        }


其中的一个重点是方法:valve.invoke(this);

这是一个递归执行过程,将this对象传入下一个valve进行处理,然后再层层深入,直到完成配置中 配置的valve流程再一层层返回。

而我们所定义的业务层的方法,也就在每一个valve中,不同种类的valve代理着不同的业务方法,这也就是为什么有的业务方法使用execute命名,有的使用doXXX作为方法名:






最终boolean返回served=true;完成请求并commitRequest。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: