(1)客户端(浏览器)发送请求,直接请求到DispatcherServlet。
(2)DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。
(3)解析到对应的Handler后,开始由HandlerAdapter适配器处理。
(4)HandlerAdapter会根据Handler来调用真正的处理器开处理请求,并处理相应的业务逻辑。
(5)处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。
(6)ViewResolver会根据逻辑View查找实际的View。
(7)DispaterServlet把返回的Model传给View。
(8)通过View返回给请求者(浏览器)
springmvc入口
1、Spring 容器初始化bean时会回调afterPropertiesSet(),实现获取通过适配HandlerMapping适配到对应的HandlerMappingAdapter。
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
==>
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
==>
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
==>
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
==>
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
2、预加载RequestMappingHandlerMapping类。该类负责将@RequestMapping的信息RequestMappingInfo信息和HanlderMethod信息到内存中
2-1、静态模块预加载文件DispatcherServlet.properties获取预加载的RequestMappingHandlerMapping类。
/**
* Name of the class path resource (relative to the DispatcherServlet class)
* that defines DispatcherServlet's default strategy names.
*/
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
}
}
2-2、初始化RequestMappingInfo(@RequestMapping注解的信息)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#createRequestMappingInfo
组装 RequestMappingInfo 模板(存储了控制层接口方法的url,请求方法,参数,请求头,接口consumes(处理请求的提交类型 content-type)接口的produces(指定接口的返回值类型))
2-3、初始化HandlerMethod(@RequestMapping注释的具体方法信息)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSet
afterPropertiesSet具体过程:
判断该bean的类型是不是标有@Controller、@RequestMapping注解的类(isHandler)。
如果是就通过aop获取标有@RequestMapping方法的具体的method信息(detectHandlerMethods),
并且将RequestMappingInfo 信息与HandlerMethod绑定起来,存入内存中。(register)
org.springframework.web.servlet.mvc.method.annotation#isHandler
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#detectHandlerMethods
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#register
3、预加载RequestMappingHandlerAdapter适配器(web九大组件之中最重要的组件),提供数据绑定、数据转换、数据校验、内容协商。
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#afterPropertiesSet
3-1、缓存@ControllerAdvice注解和@RestControllerAdvice的bean,缓存@ModelAttribute的bean和方法、缓存@InitBinder的bean和方法、缓存RequestBodyAdvice/ResponseBodyAdvice接口实现的Bean。
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#initControllerAdviceCache
3-2、初始化入参、InitBinder、返回参数解析器,并且和bean绑定。
入参解析器集合:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDefaultArgumentResolvers
@InitBinder解析器集合
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDefaultInitBinderArgumentResolvers
返回参数解析器集合
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDefaultReturnValueHandlers
各种解析器集合提供了可以根据基于注解、参数类型、用户自定义、默认参数解析器
@Nullable
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
@Nullable
private HandlerMethodArgumentResolverComposite argumentResolvers;
@Nullable
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
@Nullable
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
initControllerAdviceCache();
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
4、请求处理
org.springframework.web.servlet.DispatcherServlet#doDispatch
关键过程:
4-1、检查是否是上传请求
org.springframework.web.servlet.DispatcherServlet#checkMultipart
4-2、适配HandlerMapping(RequestMappingHandlerMapping)
前提:
spring初始化bean回调方法时候,缓存了全部的HandlerMapping。
适配过程:
根据请求找到对应的MappingRegisty和HandlerIntercepter。类、方法、拦截器、cors信息,只是实例化,并未初始化。并且存入HandlerExecutionChain的链路中。
org.springframework.web.servlet.DispatcherServlet#getHandler
4-3、根据handler适配Adapter(RequestMappingHandlerAdapter)
org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter
4-4、Adapter处理:解析方法入参、出参,并且赋值,并且和ModelAndView绑定,如果没又和ModelAndView绑定,那么直接返回null。
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
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 {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
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) {
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);
}
}
}
}