学习一个框架,首要的是要先领会它的设计思想。从抽象、从全局上来审视这个框架。其中最具有参考价值的,就是这个框架所定义的核心接口。核心接口定义了框架的骨架,也在最抽象的意义上表达了框架的设计思想。
前因:发现springMvc可以使用spring中的bean,way?
由于SpringMvc就是Servlet,必须先了解servlet原理:http://blog.csdn.net/czlpf/article/details/47781473
一。SpringMvc的入口分为 init() 和 service() 两个入口。
1.init()仅在DispatherServlet创建的时候执行一次,为容器和组件做初始化。
2.service()方法在每次http请求的时候都执行。
Servlet的所以请求都会通过执行HttpServlet中service(ServletRequest ,ServletResponse)方法,该方法执行了service(HttpServletRequest,HttpServletResponse)
而该方法在FrameworkServlet中被重写,所以执行FrameworkServlet中的service(HttpServletRequest,HttpServletResponse)方法。
—–》》FrameworkServlet.processRequest()
—–》》DispatcherServlet.doService()
—–》》DispatcherServlet.doDispatch()
这个doDispatch()就是每次http请求到springMvc的重点。
首先选择一个handler获得HandlerExecutionChain
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
其中this.handlerMappings在init()方法已经初始化。详情查看init()流程。
下面研究这个HandlerExecutionChain:
HandlerExecutionChain类的代码不长,它定义在org.springframework.web.servlet包中,为了更直观的理解,先上代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | package org.springframework.web.servlet; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.springframework.util.CollectionUtils; public class HandlerExecutionChain { private final Object handler; private HandlerInterceptor[] interceptors; private List<HandlerInterceptor> interceptorList; public HandlerExecutionChain(Object handler) { this (handler, null ); } public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) { if (handler instanceof HandlerExecutionChain) { HandlerExecutionChain originalChain = (HandlerExecutionChain) handler; this .handler = originalChain.getHandler(); this .interceptorList = new ArrayList<HandlerInterceptor>(); CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this .interceptorList); CollectionUtils.mergeArrayIntoCollection(interceptors, this .interceptorList); } else { this .handler = handler; this .interceptors = interceptors; } } public Object getHandler() { return this .handler; } public void addInterceptor(HandlerInterceptor interceptor) { initInterceptorList(); this .interceptorList.add(interceptor); } public void addInterceptors(HandlerInterceptor[] interceptors) { if (interceptors != null ) { initInterceptorList(); this .interceptorList.addAll(Arrays.asList(interceptors)); } } private void initInterceptorList() { if ( this .interceptorList == null ) { this .interceptorList = new ArrayList<HandlerInterceptor>(); } if ( this .interceptors != null ) { this .interceptorList.addAll(Arrays.asList( this .interceptors)); this .interceptors = null ; } } public HandlerInterceptor[] getInterceptors() { if ( this .interceptors == null && this .interceptorList != null ) { this .interceptors = this .interceptorList.toArray( new HandlerInterceptor[ this .interceptorList.size()]); } return this .interceptors; } @Override public String toString() { if ( this .handler == null ) { return "HandlerExecutionChain with no handler" ; } StringBuilder sb = new StringBuilder(); sb.append( "HandlerExecutionChain with handler [" ).append( this .handler).append( "]" ); if (!CollectionUtils.isEmpty( this .interceptorList)) { sb.append( " and " ).append( this .interceptorList.size()).append( " interceptor" ); if ( this .interceptorList.size() > 1 ) { sb.append( "s" ); } } return sb.toString(); } } |
乱七八糟一大堆,相信你也没全看完,也没必要全看。其实只需要看两行足矣。
?
1 2 3 | private final Object handler; private HandlerInterceptor[] interceptors; |
不出我们所料,一个实质执行对象,还有一堆拦截器。这不就是Struts2中的实现么,SpringMVC没有避嫌,还是采用了这种封装。得到HandlerExecutionChain这个执行链(execution chain)之后,下一步的处理将围绕其展开。
在Dispatcher中,执行拦截器 在执行handler之前:
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
执行handler:
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
执行handler之后:
mappedHandler.applyPostHandle(processedRequest, response, mv);
异常拦截:
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
最终执行拦截:
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
配置拦截器:
- <bean name=“/test” class=“cn.javass.chapter5.web.controller.TestController”/>
- <bean id=“handlerInterceptor1”
- class=“cn.javass.chapter5.web.interceptor.HandlerInterceptor1”/>
- <bean id=“handlerInterceptor2”
- class=“cn.javass.chapter5.web.interceptor.HandlerInterceptor2”/>
- <bean class=“org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping”>
- <property name=“interceptors”>
- <list>
- <ref bean=“handlerInterceptor1”/>
- <ref bean=“handlerInterceptor2”/>
- </list>
- </property>
- </bean>
参考:
http://my.oschina.net/lichhao/blog/99039
http://downpour.iteye.com/blog/1341459
http://blog.csdn.net/soundfly/article/details/17380111
http://sishuok.com/forum/blogCategory/showByCategory.html?categories_id=106&user_id=2