一、SpringMVC请求处理流程
二、SpringMVC各组件功能说明
名称 | 中文含义 | 提供者 | 说明 |
---|---|---|---|
DispatcherServlet | 前端控制器 | 框架提供 | 负责请求分发,处理响应结果,相当于是SpringMVC的总管家,本质是个Servlet |
HanlerMapping | 处理器映射器 | 框架提供 | 负责URL到Controller的映射,根据request查找处理的Handler |
HandlerAdapter | 处理器适配器 | 框架提供 | 负责执行对应的处理器Handler或Controller |
Handler | 处理器 | 用户提供 | 处理器又名Controller,接收请求数据,进行业务处理,返回响应结果 |
ViewResolver | 视图解析器 | 框架提供 | 解析物理视图,返回逻辑视图对象View |
View | 渲染后的视图 | 用户提供 | 如HTML、JSP、FreeMarker,将数据展现给用户 |
三、SpringMVC主要源码解读
3.1、DispatcherServlet组件详解
DispatcherServlet作为SpringMVC的总管家,根据继承关系,它继承自HttpServlet,那么它其实是一个Servlet,既然是Servlet类,那么他有一个最终的方法,就是service()方法,他是Servlet最核心的方法。查看代码可知,其中关键的核心实现主要集中在DispatcherServlet.doService方法上
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<String, Object>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
doService方法内,主要看doDispatch(request, response)方法,该方法首先根据当前请求,循环所有的处理器映射器this.handlerMappings,得到一个HandlerExecutionChain对象
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
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;
}
HandlerExecutionChain对象从名字上看是对执行链的封装,我们看下HandlerExecutionChain定义:
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
private final Object handler;
private HandlerInterceptor[] interceptors;
1、一个Object handler,对执行器的一个封装,里面包含了本次请求对应的Controller等信息。
2、一个拦截器数组HandlerInterceptor[] interceptors,拦截器HandlerInterceptor提供了3个方法preHandle、postHandle、afterCompletion
- preHandle:在处理器handler处理请求之前被调用。相当于预处理,可以进行编码、安全控制、权限校验等处理。
- postHandle:在业务处理器handler处理请求执行完成后,生成视图之前执行。
- afterCompletion:在DispatcherServlet完全处理完请求后(已经渲染了页面)被调用,可用于清理资源等。
回到主线代码,在得到一个HandlerExecutionChain对象后,然后执行了getHandlerAdapter(mappedHandler.getHandler()),通过此方法来获得一个处理器适配器对象HandlerAdapter
// 确定当前请求的处理器适配器
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
getHandlerAdapter(Object handler)其方法内部也是通过循环所有的处理器适配器,来确定将由哪个适配器来负责处理,该方法返回一个HandlerAdapter对象。
通过HandlerAdapter中的handle方法处理handler对象,并返回ModelAndView这个包含了视图和数据的对象。
可见在DispatcherServlet中,除了HandlerMapping列表,也有HandlerAdapter列表
ModelAndView mv = null;
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
得到ModelAndView对象后,后续就是渲染视图了
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
/**
* Handle the result of handler selection and handler invocation, which is
* either a ModelAndView or an Exception to be resolved to a ModelAndView.
*/
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}