spring mvc原理
spring mvc初始化
- spring容器初始化执行refresh()方法,走到最后一步finishRefresh()方法
- finishRefresh()方法内部调用ApplicationListener.onApplicationEvent方法
- spring mvc提供ContextRefreshListener类,实现ApplicationListener接口,重写onApplicationEvent方法
- onApplicationEvent方法内部调用DispatcherServlet.initStrategies方法初始化spring mvc各组件
DispatcherServlet.initStrategies()
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);// 映射器
initHandlerAdapters(context);// 适配器
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);// 视图解析器
initFlashMapManager(context);
}
spring mvc Controller类型
annotation类型:一个Controller类对应多个uri,由RequestMappingHandlerMapping解析
BeanName类型:一个Controller类对应一个uri,由BeanNameUrlHandlerMapping解析
spring mvc注册Controller方式
@Controller,annotation类型,由RequestMappingHandlerAdapter执行方法
implements Controller + @Component("/uri"),BeanName类型,由SimpleControllerHandlerAdapter执行方法
implements HttpRequestHandler + @Component("/uri"),BeanName类型,由HttpRequestHandlerAdapter执行方法
spring mvc处理请求
- doDispatch()
- checkMultipart()判断请求是否附带文件
- getHandler()根据uri去handlerMappings找Controller(扩展点HandlerMapping)
- getHandlerAdapter()根据Controller类型去handlerAdapters找适配器(扩展点HandlerAdapter)
- mappedHandler.applyPreHandle()调用拦截器的preHandle方法
- handle()执行方法并进行判断:返回、转发或者重定向
(扩展点HandlerMethodArgumentResolver方法参数类型解析器)
(扩展点HttpMessageConverter返回消息转换器)
(扩展点HandlerMethodReturnValueHandler方法返回类型解析器) - mappedHandler.applyPostHandle()调用拦截器的postHandle方法
- processDispatchResult()视图渲染(扩展点ViewResolver)
第六步补充
annotation类型Controller用反射执行方法
BeanName类型Controller用接口执行方法
doDispatch()
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 {
// 检查请求是否附带文件,根据请求头属性Content-Type判断
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
// 从缓存中取Handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 根据Controller类型找适配器
// @Controller 对应 RequestMappingHandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
// 处理http谓词
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;
}
}
// 调用拦截器的preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 执行Controller逻辑,并进行视图判断(重定向 or 转发 or 响应页面)
// @ResponseBody的处理结果为null
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 视图名称转换
applyDefaultViewName(processedRequest, mv);
// 调用拦截器的postHandle方法
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) {
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);
}
}
}
}
来源:CSDN
作者:TonnyBryant
链接:https://blog.csdn.net/qq_37956177/article/details/104021216