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。
- WebX学习二——URL请求流程分析
- webx学习(二)——Webx Framework
- Webx处理请求流程
- webx学习总结之页面流程执行过程详细分析
- webx学习(一)——初识webx
- webx学习(三)——Webx Turbine
- webx学习(四)——ResourceLoadingService
- webx学习总结之页面流程执行过程详细分析(转载)
- webx学习总结(一)——使用webx框架实现简单的登录功能
- webx—错误信息提示
- webx—Schema使用
- webx下的AnalyzeURLValve分析URL过程详细解析
- webx学习
- webx 学习
- Webx学习
- webx学习
- uboot 启动流程分析(二) — 第二阶段
- uboot 启动流程分析(二) — 第二阶段
- Unity3D实现弹幕的效果
- Android布局优化之Merge Include ViewStub使用与源码分析
- vivi的配置与编译
- 【Scala】单例对象与伴生对象
- 文本编辑器vi和vim(2)
- WebX学习二——URL请求流程分析
- oracle中rowid解决数据重复的问题
- 《编程珠玑》阅读小记(9) — 取样问题
- 【Scala】头等函数与函数即对象
- Picture控件显示jpg
- 十、迭代器和组合模式
- 黑马程序员——Java基础之函数与数组
- JS显示动态显示当前时间代码
- 【Scala】高阶函数和柯里化