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。
原文地址:http://blog.csdn.net/langduhualangdu/article/details/46507605