SpringMVC的请求处理流程图
总结
1、请求进入DispatcherServlet,由DispatcherServlet 从HandlerMappings中提取对应的Handler
2、根据Handle,然后去寻找对应的处理器适配器(HandlerAdapter),拿到对应HandlerAdapter后,这时候开始调用对应的Handler处理业务逻辑
3、执行完成之后返回一个ModeAndView,将结果交给我们的ViewResolver通过视图名称查找出对应的视图然后返回
4、渲染视图:返回渲染后的视图并响应请求
请求处理器的初始化
1、DispacterServlet中的静态块
static {
/**
* static静态块,在类加载的时候执行
* 加载springWvc的默认系统配置文件 DispatcherServlet.properties
* 配置了 HandlerAdapter HandlerMapping ThemeResolver LocaleResolver ....
* 放入到 defaultStrategies 对象中
*/
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
DispatcherServlet.properties文件
# 仅列出部分
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
2、当Servlet容器启动的时候,tomcat会调用这个DispatcherServlet的init方法
// HttpServletBean#init
public final void init() throws ServletException {
// 执行子类 FrameServlet的initServletBean方法
initServletBean();
}
// FrameworkServlet#initServletBean
protected final void initServletBean() throws ServletException {
// 初始化web环境 WebApplicationContext ==child==> ConfigurableWebApplicationContext
this.webApplicationContext = initWebApplicationContext();
// 调用了initFrameworkServlet方法,这是一个空方法
initFrameworkServlet();
}
// FrameworkServlet#initWebApplicationContext
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.webApplicationContext;
// 配置并且刷新容器
configureAndRefreshWebApplicationContext(cwac);
}
// FrameworkServlet#configureAndRefreshWebApplicationContext
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
// 添加了一个容器刷新的监听器 => ContextRefreshListener
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
// 空方法
postProcessWebApplicationContext(wac);
// 容器的初始化共组
applyInitializers(wac);
// 刷新容器,走到AbstractApplicationContext中的refresh方法
wac.refresh();
}
3、容器刷新时触发的监听器ContextRefreshListener
// FrameworkServlet.ContextRefreshListener
private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
FrameworkServlet.this.onApplicationEvent(event);
}
}
public void onApplicationEvent(ContextRefreshedEvent event) {
this.refreshEventReceived = true;
synchronized (this.onRefreshMonitor) {
onRefresh(event.getApplicationContext());
}
}
// 调用子类的onRefresh方法
// DispatcherServlet#onRefresh
protected void onRefresh(ApplicationContext context) {
// 初始化策略组件
initStrategies(context);
}
4、初始化组件
// DispatcherServlet#initStrategies
protected void initStrategies(ApplicationContext context) {
// 初始化文件上传组件 beanName="multipartResolver"
initMultipartResolver(context);
// 初始化国际化组件 beanName="localeResolver"
initLocaleResolver(context);
// 初始化主题解析器,利用spring来做 beanName="themeResolver"
initThemeResolver(context);
// 初始化处理映射器 beanName="handlerMapping"
initHandlerMappings(context);
// 初始化处理器适配器 beanName="handlerAdapter"
initHandlerAdapters(context);
// 初始化异常处理器 beanName="handlerExceptionResolver"
initHandlerExceptionResolvers(context);
// 视图解析器,在view为空时,根据请求来获取视图名称 beanName="viewNameTranslator"
initRequestToViewNameTranslator(context);
// 初始化视图解析器 beanName="viewResolver"
initViewResolvers(context);
// 重定向数据管理器 beanName="flashMapManager"
initFlashMapManager(context);
}
初始化的组件中MultipartResolver、LocaleResolver、ThemeResolver、RequestToViewNameTranslator和FlashMapManager的初始化是直接去容器中获取对应的bean对象。
其他的组件默认会去容器中寻找所有的 对应类型 的对象。如果在容器中没有找到对应的对象,那么就会向容器中注册 DispatcherServlet.properties 文件中的对应的类。
// 去DispatcherServlet.properties文件中获取 strategyInterface 对应的组件
// 找到之后会将组件注册到DispatcherServlet的对应属性上
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
// 传入的class全名,就对应了DispatcherServlet.properties中的key
String key = strategyInterface.getName();
// 从配置文件中拿出配置
String value = defaultStrategies.getProperty(key);
if (value != null) {
// 截取value中的 , 返回一个className 的数组
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<>(classNames.length);
for (String className : classNames) {
// 根据反射创建出这个class对象
Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
// 根据这个class 去createBean,这里就可以将 HandlerMapping 的组件放入容器中
Object strategy = createDefaultStrategy(context, clazz);
// 最后把策略对象返回
strategies.add((T) strategy);
}
return strategies;
} else {
return new LinkedList<>();
}
}
请求处理器处理请求
SpringMVC的核心处理器:DispatcherServlet,它本质上也是一个HttpServlet,在配置SpringMVC的时候,我们会让这个servlet随着servlet容器的启动而启动(load-on-startup),并且拦截所有对当前应用程序的请求。
所以当请求来了之后,首先会调用HttpServlet#service方法。具体会调用父类FrameworkServlet#service
// FrameworkServlet#service
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
// // 增加对HttpMethod.PATCH的支持
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
processRequest(request, response);
} else {
// HttpServlet#service 进行请求类型的分发 -> 走到doGet/doPost/doPut
// 最终都会和上面的一致调用 processRequest(request, response);
super.service(request, response);
}
}
处理请求之前的一些准备
org.springframework.web.servlet.FrameworkServlet#processRequest
-> org.springframework.web.servlet.DispatcherServlet#doService
-> org.springframework.web.servlet.DispatcherServlet#doDispatch
处理请求的核心方法:DispatcherServlet#doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 检查是否存在文件上传
HttpServletRequest processedRequest = checkMultipart(request);
boolean multipartRequestParsed = (processedRequest != request);
// 确定当前请求是由哪一种handlerMapping来处理
// 一种是选择一个bean来处理,另一种是映射到一个方法上
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
// 根据当前的请求的 handlerMapping 来决定使用哪一种处理器适配器
// HttpRequestHandlerAdapter
// SimpleControllerHandlerAdapter
// RequestMappingHandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 执行所有配置这个uri的拦截器的 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
// 只要存在一个拦截器的 preHandle 方法返回false,这里就会直接return
return;
}
/** 调用实际的处理器来处理请求
如果是匹配一个类的话,这里会直接把这个映射对象传入 => mappedHandler.getHandler()
HttpRequestHandlerAdapter => handle() => handler.handleRequest(request, response)
SimpleControllerHandlerAdapter => handle() => handler.handleRequest(request, response);
RequestMappingHandlerAdapter
=> AbstractHandlerMethodAdapter#handle
=> RequestMappingHandlerAdapter#handleInternal
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
*/
// 是否是异步请求
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 如果存在mv对象,但是在mv中不存在view,这里就会应用一个默认的视图对象
applyDefaultViewName(processedRequest, mv);
// 执行所有配置这个uri的拦截器的 postHandle 方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 处理返回值,渲染页面,返回响应...
// 在这里面的最后一个执行所有配置这个uri的拦截器的 afterCompletion 方法
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
doDispatch方法就是SpringMVC中请求处理流程的具体代码实现。
核心组件 - HandlerMapping
在DispatcherServlet.properties中HandlerMapping组件存在两种实现BeanNameUrlHandlerMapping和RequestMappingHandlerMapping
根据HandlerMapping中的getHandler方法来确定使用哪一种HandlerMapping。
// DispatcherServlet#getHandler
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings == null) return null;
// 遍历所有的handlerMappings
for (HandlerMapping mapping : this.handlerMappings) {
// 这里返回这个请求对应的拦截器链
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) return handler;
}
}
这里的getHandler方法非常关键,它不仅找出了需要使用的HandlerMapping还会去构建好拦截器链。
public final HandlerExecutionChain getHandler(HttpServletRequest request) {
// 确定使用哪一类的请求处理器
// AbstractHandlerMethodMapping.getHandlerInternal -> RequestMappingHandlerMapping
// AbstractUrlHandlerMapping.getHandlerInternal -> BeanNameUrlHandlerMapping
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// 构建拦截器链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
return executionChain;
}
HandlerMapping
1、AbstractHandlerMethodMapping.getHandlerInternal
// @RequestMapping这种servlet
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// uri localhost:9090/index => /index
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
// 读锁
this.mappingRegistry.acquireReadLock();
try {
// 根据uri获取对应的处理方法
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
} finally {
this.mappingRegistry.releaseReadLock();
}
}
2、AbstractUrlHandlerMapping.getHandlerInternal
// @Component("/index/2") 这种controller
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
// handlerMap<String, Object>中找可以找到
Object handler = lookupHandler(lookupPath, request);
if (handler != null) {
return handler;
}
// 省略部分代码
}
构建拦截器链
只有在找出对应的HandlerMapping后才会构建拦截器链
// AbstractHandlerMapping#getHandlerExecutionChain
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
// uri
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
// 遍历所有的拦截器 我们自己实现了HandlerInterceptor会被springMVC包装为MappedInterceptor
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
调用MappedInterceptor#matches进行拦截器匹配
// addPathPatterns -> includePatterns
// excludePathPatterns -> excludePatterns
public boolean matches(String lookupPath, PathMatcher pathMatcher) {
PathMatcher pathMatcherToUse = (this.pathMatcher != null ? this.pathMatcher : pathMatcher);
if (!ObjectUtils.isEmpty(this.excludePatterns)) {
for (String pattern : this.excludePatterns) {
if (pathMatcherToUse.match(pattern, lookupPath)) {
return false;
}
}
}
if (ObjectUtils.isEmpty(this.includePatterns)) {
return true;
}
for (String pattern : this.includePatterns) {
if (pathMatcherToUse.match(pattern, lookupPath)) {
return true;
}
}
return false;
}
获取处理器适配器
这里的handlerAdapters默认就是DispatcherServlet.properties中配置的三种拦截器适配器
- HttpRequestHandlerAdapter 匹配HttpRequestHandler处理器
- SimpleControllerHandlerAdapter 匹配实现了Controller接口或继承了AbstractController的类
- RequestMappingHandlerAdapter 匹配HandlerMethod,@Controller注解
// HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
// 核心的supports方法
if (adapter.supports(handler)) {
return adapter;
}
}
}
}
// HttpRequestHandlerAdapter#supports
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
// SimpleControllerHandlerAdapter#supports
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
// AbstractHandlerMethodAdapter#supports
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
// RequestMappingHandlerAdapter#supportsInternal
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
拦截器回调 - preHandle
// if (!mappedHandler.applyPreHandle(processedRequest, response)) {}
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
// 每一个拦截器的 preHandle 需要返回true,整个请求处理才能继续向下执行
if (!interceptor.preHandle(request, response, this.handler)) {
// 如果有一个拦截器的 preHandle 方法返回了false,就会直接执行直接拦截器 afterCompletion 方法,并返回false
triggerAfterCompletion(request, response, null);
// 返回false意味着这个请求的处理就到此结束了
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
处理器处理请求
以处理@Controller注解为例:AbstractHandlerMethodAdapter#handle
// mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
/** 调用子类的 handleInternal 方法
* 不同的处理器适配器实现了不同功能的 handleInternal 方法
* RequestMappingHandlerAdapter#handleInternal 处理@RequestMapping方法映射
*/
return handleInternal(request, response, (HandlerMethod) handler);
}
// RequestMappingHandlerAdapter#handleInternal
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// 在这个同步块中执行controller回调方法
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
// 执行映射方法
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
// json 数据格式的响应在上面就完成了 invokeHandlerMethod 方法中
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
回调拦截器 - postHandle
检查返回的ModelAndView和回调拦截器 - postHandle
// 如果存在mv对象,但是在mv中不存在view,这里就会应用一个默认的视图对象
applyDefaultViewName(processedRequest, mv);
// 执行所有配置这个uri的拦截器的 postHandle 方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 是否需要创建默认的视图对象
private void applyDefaultViewName(HttpServletRequest request, ModelAndView mv) {
if (mv != null && !mv.hasView()) {
// 存在mv对象,但是不存在view对象才会执行到这里:DefaultRequestToViewNameTranslator
// DefaultRequestToViewNameTranslator#getViewName 方法
// 会根据请求的URI返回视图名称,去除后缀,前后/,如果完全匹配,就返回请求的URI
String defaultViewName = getDefaultViewName(request);
if (defaultViewName != null) {
mv.setViewName(defaultViewName);
}
}
}
调用拦截器 - afterCompletion
// processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,HandlerExecutionChain mappedHandler,
ModelAndView mv,Exception exception) {
boolean errorView = false;
if (exception != null) {
// 如果存在异常,就把异常交给HandlerExceptionResolver来处理
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
} else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
// 调用 HandlerExceptionResolver#resolveException
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);
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
// 在视图渲染等一切工作完成之后执行拦截器的 afterCompletion 方法
// interceptor.afterCompletion(request, response, this.handler, ex);
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
SpringMVC对于beanName请求的处理
如果一个请求可以匹配到一个实现了Controller接口或者继承了AbstractController的bean对象。那么可以直接调用接口或者抽象方法去处理请求。
// SimpleControllerHandlerAdapter -> 直接调用Controller接口的方法
// AbstractController会在handleRequest中调用子类的handleRequestInternal方法
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
// HttpRequestHandlerAdapter
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}