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

来源:互联网 发布:软件项目外包平台 编辑:程序博客网 时间:2024/06/05 05:51

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。

0 0
原创粉丝点击