5.1 前端控制器 DispatcherServlet
继承结构:
前端请求进来,会执行FrameworkServlet的doGet/doPost方法,而doGet/doPost方法都会执行processRequest(request,response)方法,processRequest()主要做的事情有:
- 获取到上一个请求保存的LocaleContext,建立新的LocaleContext
- 获取到上一个请求保存的RequestAttributes,建立新的RequestAttributes
调用抽象方法doService(),此方法由继承该类的DispatcherServlet类来实现
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// 获取到上一个请求保存的LocaleContext
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
// 建立新的LocaleContext
LocaleContext localeContext = buildLocaleContext(request);
// 获取到上一个请求保存的RequestAttributes
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 建立新的RequestAttributes
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
// 新的RequestAttributes绑定到LocalThread
initContextHolders(request, localeContext, requestAttributes);
try {
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
DisapatcherServlet类的doService方法主要做的事情:
- 获取请求域中的属性名存起来做个副本
- 往request设置一些属性值使框架对象可用于处理程序和视图对象
- flashMapManager管理重定向参数携带
执行doDispatcher()方法
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(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<>();
// 获取请求域中的属性名存起来做个副本
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));
}
}
}
// 往request设置一些属性值使框架对象可用于处理程序和视图对象
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());
// flashMapManager管理重定向参数携带
if (this.flashMapManager != null) {
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);
}
}
}
}
5.2 核心方法doDisapatcher()分析
该方法是SpringMVC的核心方法,具体做的事情如下:
- 1. 检查是否文件上传的请求
- 2. 取得当前请求的Controller,也称为Handler,即处理器。这里并不是直接返回Controller,而是返 回HandlerExecutionChain请求处理链对象,该对象封装了Handler和Interceptor。如果handler为空则返回404。
- 3 .获取处理请求的处理器适配器HandlerAdapter,处理last-modified请求头。
- 4. 实际处理器处理请求,返回结果视图对象ModelAndView,结果视图对象处理
- 5. 最终会调用HandlerInterceptor的afterCompletion方法 ```java protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try { ModelAndView mv = null; Exception dispatchException = null;
try {
// 1.检查是否文件上传的请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
/**
* 2.取得当前请求的Controller,也称为Handler,即处理器
* 这里并不是直接返回Controller,而是返回HandlerExecutionChain请求处理链对象
* 该对象封装了Handler和Interceptor
*/
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
// 如果handler为空则返回404
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 3.获取处理请求的处理器适配器HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
// 处理last-modified请求头
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 4. 实际处理器处理请求,返回结果视图对象ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 结果视图对象处理
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
} processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { // 最终会调用HandlerInterceptor的afterCompletion方法 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", 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);
}
5.3 SpringMVC的核心步骤
调⽤getHandler()获取到能够处理当前请求的执⾏链 HandlerExecutionChain(Handler+拦截器)
- 调⽤getHandlerAdapter();获取能够执⾏1)中Handler的适配器
- 适配器调⽤Handler执⾏ha.handle(总会返回⼀个ModelAndView对象)
调⽤processDispatchResult()⽅法完成视图渲染跳转
5.3.1 getHandler方法分析
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 遍历handlerMappings,里面有两个HandlerMapping的实现类
// 分别是BeanNameUrlHandlerMapping和RequestMappingHandlerMapping
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
// 容器初始化的时候通过扫描注解,配置了url和handler的关系
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
// 返回的HandlerExecutionChain包含了Handler和Interceptor信息
return handler;
}
}
}
return null;
}
5.3.2 getHandlerAdapter方法分析
// 通过Handler匹配到支持的Adapter适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
/**
* HandlerAdapter的三个实现类 判断支持那个然后返回
* 1.HttpRequestHandlerAdapter
* 2.SimpleControllerHandlerAdapter
* 3.RequestMappingHandlerAdapter
*/
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
5.3.3 适配器调⽤Handler执⾏ha.handle()方法
mav.invokeHandlerMethod(request,response,handlerMethod)
- 对handlerMethod进行参数等的适配处理,并调用目标handler
- 对请求参数进行处理,调用目标HanderMethod,并且将返回值封装成MethodAndView对象
- 对目标handler的参数进行处理,并且调用目标handler
- 将request中参数转换成当前handler的参数形式
- doInvole()方法主要结合处理后的参数,使用反射对目标方法进行调用
5.3.4 processDispatchResult()完成视图渲染跳转
```java private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
// Did the handler return a view to render? if (mv != null && !mv.wasCleared()) {@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
}// 是否处理返回渲染的视图
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) { View view; String viewName = mv.getViewName(); if (viewName != null) { // We need to resolve the view name. // 解析封装视图 view = resolveViewName(viewName, mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException(“Could not resolve view with name ‘“ + mv.getViewName() + “‘ in servlet with name ‘“ + getServletName() + “‘“); } } }
protected View resolveViewName(String viewName, @Nullable Map
```java
// 在解析出View视图对象的过程中会判断是否重定向、是否转发等,不同的情况封装的是不同的
// View实现
@Override
protected View createView(String viewName, Locale locale) throws Exception {
// If this resolver is not supposed to handle the given view,
// return null to pass on to the next resolver in the chain.
if (!canHandle(viewName, locale)) {
return null;
}
// Check for special "redirect:" prefix.
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
RedirectView view = new RedirectView(redirectUrl,
isRedirectContextRelative(), isRedirectHttp10Compatible());
String[] hosts = getRedirectHosts();
if (hosts != null) {
view.setHosts(hosts);
}
return applyLifecycleMethods(REDIRECT_URL_PREFIX, view);
}
// Check for special "forward:" prefix.
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
InternalResourceView view = new InternalResourceView(forwardUrl);
return applyLifecycleMethods(FORWARD_URL_PREFIX, view);
}
// Else fall back to superclass implementation: calling loadView.
return super.createView(viewName, locale);
}
@Override
public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("View " + formatViewName() +
", model " + (model != null ? model : Collections.emptyMap()) +
(this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
}
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
prepareResponse(request, response);
// 把modelMap中的数据暴露到request请求域中
// 这也是后台model.add后视图可以从请求域中取出的原因
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
5.4 MVC九大组件分析
- MVC的九大组件在DispatcherServlet类中都有定义。 ```java /* MultipartResolver used by this servlet. / // 多部件解析器 @Nullable private MultipartResolver multipartResolver;
/* LocaleResolver used by this servlet. / // 区域化 国际化解析器 @Nullable private LocaleResolver localeResolver;
/* ThemeResolver used by this servlet. / // 主题解析器 @Nullable private ThemeResolver themeResolver;
/* List of HandlerMappings used by this servlet. /
// 处理器映射器组件
@Nullable
private List
/* List of HandlerAdapters used by this servlet. /
// 处理器适配器组件
@Nullable
private List
/* List of HandlerExceptionResolvers used by this servlet. /
// 异常解析器组件
@Nullable
private List
/* RequestToViewNameTranslator used by this servlet. / // 默认视图名转换器组件 @Nullable private RequestToViewNameTranslator viewNameTranslator;
/* FlashMapManager used by this servlet. / // flash属性管理组件 重定向属性 @Nullable private FlashMapManager flashMapManager;
/* List of ViewResolvers used by this servlet. /
// 视图解析器
@Nullable
private List
2. 九⼤组件都是定义了接⼝,接⼝其实就是定义了该组件的规范,⽐如ViewResolver、HandlerAdapter等都是接⼝
3. 九大组件初始化入口
```java
@Override
protected void onRefresh(ApplicationContext context) {
// 初始化策略
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
// 初始化多文件上传组件
initMultipartResolver(context);
// 初始化本地语言环境
initLocaleResolver(context);
// 初始化主题模板处理器
initThemeResolver(context);
// 初始化处理器映射器
initHandlerMappings(context);
// 初始化处理器适配器
initHandlerAdapters(context);
// 初始化异常拦截器
initHandlerExceptionResolvers(context);
// 初始化视图预处理器
initRequestToViewNameTranslator(context);
// 初始化视图转换器
initViewResolvers(context);
// 初始化FlashMap管理器
initFlashMapManager(context);
}
解析initHandlerMappings:如果按照类型和按照固定id从ioc容器中找不到对应组件,则会按照默认策略进⾏注册初始化,默认策略在DispatcherServlet.properties⽂件中配置
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// 按照HandlerMapping.class类型去ioc容器中找到所有的HandlerMapping
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
try {
// 否则在ioc中按照固定名称id(handlerMapping)去查找
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// 最后还为控则按照默认策略生成(按照默认方式实例化生成HandlerMapping)
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}