阅读须知
- Spring源码版本:4.3.8
- 文章中使用/* */注释的方法会做深入分析
正文
承接上文,我们知道 HttpServlet 提供一些处理请求的方法,如 doGet、doPost、service等,在 DispatcherServlet 中的实现都调用了 processRequest 方法,我们来分析这个方法:
FrameworkServlet:
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
FrameworkServlet:
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 = buildLocaleContext(request);
// 提取当前线程的 RequestAttributes
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 封装请求参数
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
// 构建异步请求管理器,异步请求是 Spring3.2 版本的新特性
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
// 注册 Callable 拦截器
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
// 保存到当前线程,保证当前线程的请求还能获取到
initContextHolders(request, localeContext, requestAttributes);
try {
/* 子类具体实现处理请求逻辑 */
doService(request, response);
}
catch (ServletException ex) {
failureCause = ex;
throw ex;
}
catch (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();
}
if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request", failureCause);
}
else {
if (asyncManager.isConcurrentHandlingStarted()) {
logger.debug("Leaving response open for concurrent processing");
}
else {
this.logger.debug("Successfully completed request");
}
}
}
publishRequestHandledEvent(request, response, startTime, failureCause); // 发布事件通知
}
}
这里提到了异步请求,这里给出Spring对异步请求介绍和应用示例的官方文档地址,大家可以进行查阅了解。
DispatcherServlet:
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) + "]");
}
// 保存请求属性的快照,以便于包含之后还能够恢复原始属性
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("org.springframework.web.servlet")) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// 为请求包含一些属性(将之前初始化好的一些策略对象放入请求属性中)
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()) {
if (attributesSnapshot != null) {
// 根据之前保存的请求属性快照将请求属性恢复到原始状态
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
DispatcherServlet:
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 {
/* 检查是否是 multipart 类型的请求,如果是,将请求对象转换为 MultipartHttpServletRequest 类型的请求 */
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
/* 根据 request 找到对应的 handler */
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
// 没有 handler 通过 response 对象返回错误信息
noHandlerFound(processedRequest, response);
return;
}
/* 根据 handler 找到对应的 HandlerAdapter */
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
// 如果 handler 支持处理 last-modified 请求,则处理
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;
}
}
/* 调用拦截器的 preHandle 方法 */
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
/* 真正的请求处理 */
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) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
/* 处理请求结果 */
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 拦截器 afterCompletion 方法的调用
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
// 拦截器 afterCompletion 方法的调用
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
// 如果是异步请求,则调用 AsyncHandlerInterceptor 的 afterConcurrentHandlingStarted 代替普通拦截器的 postHandle 和 afterCompletion 方法
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
if (multipartRequestParsed) {
// 清理一些 multipart 类型请求的资源
cleanupMultipart(processedRequest);
}
}
}
}
DispatcherServlet:
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
"this typically results from an additional MultipartFilter in web.xml");
}
else if (hasMultipartException(request) ) {
logger.debug("Multipart resolution failed for current request before - " +
"skipping re-resolution for undisturbed error rendering");
}
else {
try {
return this.multipartResolver.resolveMultipart(request);
}
catch (MultipartException ex) {
if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) {
logger.debug("Multipart resolution failed for error dispatch", ex);
}
else {
throw ex;
}
}
}
}
return request;
}
这里使用之前初始化的 multipartResolver 来判断和解析文件上传请求,这里需要注意的是,multipartResolver 没有默认的策略,所以如果我们的系统需要处理文件上传,就必须配置 multipartResolver,Spring 为我们提供了两种处理类,第一个 StandardServletMultipartResolver,是基于 Servlet3.0 API 来实现的,另一个 CommonsMultipartResolver 是基于 apache 的 commons-fileupload 包实现的,使用时需要引入相关 jar 包。
DispatcherServlet:
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() + "'");
}
// 获取 handler 请求处理链
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
这里获取 handler 请求处理链会涉及到 SpringMVC 中一个重要的角色 HandlerMapping,关于 HandlerMapping 的源码解析详见SpringMVC源码解析之HandlerMapping。下面是根据 Handler 获取 HandlerAdapter 适配器:
DispatcherServlet:
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
/* 判断当前 HandlerAdapter 是否支持当前 Handler */
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");
}
这里的 handlerAdapters 在上面初始化的过程中在用户不指定的情况下,Spring 会默认注册三个策略,分别为HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter,其中 HttpRequestHandlerAdapter 用来适配实现了 HttpRequestHandler 的 handler,SimpleControllerHandlerAdapter 用于适配继承了 AbstractController 和实现了 Controller 接口的 Controller,AnnotationMethodHandlerAdapter 在 Spring3.2 版本被注解了 @Deprecated,已经不推荐使用了,用 RequestMappingHandlerAdapter 代替,用于适配注解了 @Controller 和 @RequestMapping 的 Controller,这种也是我们最常用的方式,我们就以 RequestMappingHandlerAdapter 为例来进行分析:
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
我们在分析注解方式的 handler 注册的过程时看到了,handler 被封装成了 HandlerMethod,所以这里会匹配注解方式注册的 handler。接下来是对 Last-Modified 缓存机制的支持,简单介绍一下 Last-Modified 缓存机制,在客户端第一次输入 URL 时,服务器端会返回内容和状态码200,表示请求成功,同时会添加一个 Last-Modified 响应头,表示该请求内容在服务器上的最后更新时间,客户端第二次请求相同的 URL 时,客户端会向服务器发送请求头 If-Modified-Since 询问服务器该时间之后当前请求内容是否有被修改过,如果内容没有变化,则自动返回 HTTP304 状态码,内容为空,这样就节省了网络带宽。下面是拦截器 preHandle 方法的调用:
HandlerExecutionChain:
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
// 遍历拦截器调用 preHandle 方法
if (!interceptor.preHandle(request, response, this.handler)) {
// 如果有没通过的,遍历拦截器调用 afterCompletion 方法
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
下面就是真正的请求处理阶段了,调用 HandlerAdapter 的 handle 方法,我们同样以 RequestMappingHandlerAdapter 来分析,首先看一下它的类层次结构:
我们发现它实现了 InitializingBean,所以分析一下 afterPropertiesSet 方法的实现:
RequestMappingHandlerAdapter:
public void afterPropertiesSet() {
/* 初始化 ControllerAdvice 缓存 */
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);
}
}
RequestMappingHandlerAdapter:
private void initControllerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
if (logger.isInfoEnabled()) {
logger.info("Looking for @ControllerAdvice: " + getApplicationContext());
}
// 获取@ControllerAdvice注解的beanName,并封装到ControllerAdviceBean中
List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
AnnotationAwareOrderComparator.sort(beans);
List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>();
for (ControllerAdviceBean bean : beans) {
// 获取@ModelAttribute注解的方法
Set<Method> attrMethods = MethodIntrospector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(bean, attrMethods); // 记录到相应缓存中
if (logger.isInfoEnabled()) {
logger.info("Detected @ModelAttribute methods in " + bean);
}
}
// 获取@InitBinder注解的方法
Set<Method> binderMethods = MethodIntrospector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(bean, binderMethods); // 记录到相应缓存中
if (logger.isInfoEnabled()) {
logger.info("Detected @InitBinder methods in " + bean);
}
}
// RequestBodyAdvice类型bean的记录
if (RequestBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
requestResponseBodyAdviceBeans.add(bean);
if (logger.isInfoEnabled()) {
logger.info("Detected RequestBodyAdvice bean in " + bean);
}
}
if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
requestResponseBodyAdviceBeans.add(bean);
if (logger.isInfoEnabled()) {
logger.info("Detected ResponseBodyAdvice bean in " + bean);
}
}
}
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
}
}
RequestMappingHandlerAdapter:
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
// 添加各种注解参数解析器
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); // @RequestParam
resolvers.add(new RequestParamMapMethodArgumentResolver()); // @RequestParam,参数为Map类型
resolvers.add(new PathVariableMethodArgumentResolver()); // @PathVariable
resolvers.add(new PathVariableMapMethodArgumentResolver()); // @PathVariable,参数为Map类型
resolvers.add(new MatrixVariableMethodArgumentResolver()); // @MatrixVariable
resolvers.add(new MatrixVariableMapMethodArgumentResolver()); // @MatrixVariable,参数为Map类型
resolvers.add(new ServletModelAttributeMethodProcessor(false)); // @ModelAttribute
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); // @RequestBody
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice)); // @RequestPart
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); // @RequestHeader
resolvers.add(new RequestHeaderMapMethodArgumentResolver()); // @RequestHeader,参数为Map类型
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory())); // @CookieValue
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); // @Value
resolvers.add(new SessionAttributeMethodArgumentResolver()); // @SessionAttribute
resolvers.add(new RequestAttributeMethodArgumentResolver()); // @RequestAttribute
// 添加各种类型参数解析器
resolvers.add(new ServletRequestMethodArgumentResolver()); // 请求类型的参数,如ServletRequest、MultipartRequest、HttpSession等
resolvers.add(new ServletResponseMethodArgumentResolver()); // 响应类型的参数,如ServletResponse等
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); // HttpEntity、RequestEntity类型的参数和返回值
resolvers.add(new RedirectAttributesMethodArgumentResolver()); // RedirectAttributes类型的参数
resolvers.add(new ModelMethodProcessor()); // Model类型的参数和返回值
resolvers.add(new MapMethodProcessor()); // Map类型的参数和返回值
resolvers.add(new ErrorsMethodArgumentResolver()); // Errors类型的参数
resolvers.add(new SessionStatusMethodArgumentResolver()); // SessionStatus类型的参数
resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); // UriComponentsBuilder类型的参数
// 自定义参数解析器
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// 上面已经添加过,这里不同的是构造方法的第二个参数传了true,表示使用默认的解析方法,当参数是一个简单类型的时候,会把请求参数的名称看做方法参数的名称
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
// 上面已经添加过,这里不同的是构造方法的参数传了true,表示非简单类型的参数和返回值会被看作为model属性
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
初始化各种资源之后,下面是请求处理的过程:
AbstractHandlerMethodAdapter:
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
/* 处理请求 */
return handleInternal(request, response, (HandlerMethod) handler);
}
RequestMappingHandlerAdapter:
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request); // 请求校验,主要是校验请求的method是否支持和session的必要性校验
if (this.synchronizeOnSession) { // 如果需要session内的同步执行
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session); // 获取session锁
synchronized (mutex) {
/* 调用HandlerMethod */
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
/* 调用HandlerMethod */
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
/* 调用HandlerMethod */
mav = invokeHandlerMethod(request, response, handlerMethod);
}
// 对Cache-Control的支持
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
// 如果有session属性(如@SessionAttributes注解的controller)
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
RequestMappingHandlerAdapter:
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
/* 获取数据绑定工厂 */
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
/* 获取 Model 工厂 */
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 封装 HandlerMethod
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
/* 初始化 Model */
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
// 创建异步请求对象,这里会根据 servlet 的 ServletRequest 接口类是否包含 startAsync 方法来判断是否支持异步请求,servlet3.0 开始支持异步请求
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
// 创建异步请求管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
// 判断是否有并发返回值,如果有需要进行包装
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
/* 调用方法,处理返回结果 */
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
// 如果是异步请求直接返回 null,不会走下面构建 ModelAndView 的逻辑,判断是否是异步请求的逻辑是调用 servlet 的 API,检查是否调用了 startAsync 方法将当前请求放入了异步模式中
return null;
}
// 构建 ModelAndView 并返回
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
// 请求销毁的回调,session 的处理
webRequest.requestCompleted();
}
}
RequestMappingHandlerAdapter:
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
Class<?> handlerType = handlerMethod.getBeanType();
Set<Method> methods = this.initBinderCache.get(handlerType);
if (methods == null) {
// 获取 @InitBinder 注解的方法
methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
this.initBinderCache.put(handlerType, methods);
}
List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>();
// initBinderAdviceCache 缓存的初始化过程在上文分析过
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache.entrySet()) {
// 根据包名、类型、注解判断当前 ControllerAdviceBean 是否可以应用到目标 handler 类
if (entry.getKey().isApplicableToBeanType(handlerType)) {
Object bean = entry.getKey().resolveBean();
for (Method method : entry.getValue()) {
// 封装到 InvocableHandlerMethod 中
initBinderMethods.add(createInitBinderMethod(bean, method));
}
}
}
for (Method method : methods) {
Object bean = handlerMethod.getBean();
// 封装到 InvocableHandlerMethod 中
initBinderMethods.add(createInitBinderMethod(bean, method));
}
// 创建数据绑定工厂
return createDataBinderFactory(initBinderMethods);
}
RequestMappingHandlerAdapter:
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
// 从缓存中获取 SessionAttributesHandler,没有则创建并放入缓存
SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
Class<?> handlerType = handlerMethod.getBeanType();
Set<Method> methods = this.modelAttributeCache.get(handlerType);
if (methods == null) {
// 获取 @ModelAttribute 注解的方法
methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
this.modelAttributeCache.put(handlerType, methods);
}
List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>();
// modelAttributeAdviceCache 的注册过程上文分析过
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {
// 根据包名、类型、注解判断当前 ControllerAdviceBean 是否可以应用到目标 handler 类
if (entry.getKey().isApplicableToBeanType(handlerType)) {
Object bean = entry.getKey().resolveBean();
for (Method method : entry.getValue()) {
// 封装到 InvocableHandlerMethod 中
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
}
}
for (Method method : methods) {
Object bean = handlerMethod.getBean();
// 封装到 InvocableHandlerMethod 中
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
}
ModelFactory:
public void initModel(NativeWebRequest request, ModelAndViewContainer container,
HandlerMethod handlerMethod) throws Exception {
// 检索 session 属性
Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
// 合并到 ModelAndView 容器,放入 ModelMap 中
container.mergeAttributes(sessionAttributes);
/* 调用 model 属性方法填充 model,仅仅填充那些 model 中没有出现的的属性 */
invokeModelAttributeMethods(request, container);
// 获取 handlerMethod 的方法参数上注解的 @ModelAttribute 的 name 属性
for (String name : findSessionAttributeArguments(handlerMethod)) {
if (!container.containsAttribute(name)) {
// 检索 session 属性
Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
if (value == null) {
throw new HttpSessionRequiredException("Expected session attribute '" + name + "'", name);
}
container.addAttribute(name, value);
}
}
}
ModelFactory:
private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container)
throws Exception {
while (!this.modelMethods.isEmpty()) {
// 这里获取的 modelMethod 是在构造 ModelFactory 时传入的从 ControllerAdviceBean 和 HandlerMethod 中提取的由 @ModelAttribute 注解的方法,这里会提取并从缓存中移除掉
InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();
ModelAttribute ann = modelMethod.getMethodAnnotation(ModelAttribute.class);
// 如果容器的 ModelMap 的 key 中已经包含当前注解的 name 值,则不在调用
if (container.containsAttribute(ann.name())) {
if (!ann.binding()) {
// 如果注解的 binding 属性设置为 false,则添加到不可用绑定属性集合中
container.setBindingDisabled(ann.name());
}
continue;
}
/* 调用 HandlerMethod,这里调用的是 ModelMethod */
Object returnValue = modelMethod.invokeForRequest(request, container);
if (!modelMethod.isVoid()){
// 获取返回值名称,按照如下顺序,首先获取注解声明的 value 属性,为空则判断声明的返回值类型是否比 Object 类型更具体,否则使用实际的返回值类型
String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());
if (!ann.binding()) {
container.setBindingDisabled(returnValueName);
}
if (!container.containsAttribute(returnValueName)) {
container.addAttribute(returnValueName, returnValue);
}
}
}
}
InvocableHandlerMethod:
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
/* 获取当前请求的方法参数 */
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
"' with arguments " + Arrays.toString(args));
}
/* 调用 */
Object returnValue = doInvoke(args);
if (logger.isTraceEnabled()) {
logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
"] returned [" + returnValue + "]");
}
return returnValue;
}
InvocableHandlerMethod:
private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
// 遍历方法参数列表
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
// 试图从提供的参数值列表中解析方法参数
args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
// 这里的 argumentsResolvers 我们在分析 RequestMappingHandlerAdapter 的 afterPropertiesSet 方法时看到过它的初始化过程,并且在构建 InvocableHandlerMethod 时 set 进来的
/* 判断是否支持解析当前方法参数 */
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
/* 解析方法参数 */
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug(getArgumentResolutionErrorMessage("Failed to resolve", i), ex);
}
throw ex;
}
}
if (args[i] == null) {
throw new IllegalStateException("Could not resolve method parameter at index " +
parameter.getParameterIndex() + " in " + parameter.getMethod().toGenericString() +
": " + getArgumentResolutionErrorMessage("No suitable resolver for", i));
}
}
return args;
}
参数解析器在初始化过程中创建很多种,并将它们都封装到了组合类中,这里我们以RequestParamMethodArgumentResolver为例来分析解析过程。
HandlerMethodArgumentResolverComposite:
public boolean supportsParameter(MethodParameter parameter) {
// 判断是否支持解析就是判断适合当前方法参数的解析器是否为null
return (getArgumentResolver(parameter) != null);
}
HandlerMethodArgumentResolverComposite:
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
if (logger.isTraceEnabled()) {
logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +
parameter.getGenericParameterType() + "]");
}
/* 遍历封装的所有ArgumentResolver,判断是否支持当前参数的解析 */
if (methodArgumentResolver.supportsParameter(parameter)) {
result = methodArgumentResolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
RequestParamMethodArgumentResolver:
public boolean supportsParameter(MethodParameter parameter) {
// 如果参数有@RequestParam注解,需要判断是否是Map类型,如果是注解必须指定具体的名称,否则交给RequestParamMapMethodArgumentResolver解析
if (parameter.hasParameterAnnotation(RequestParam.class)) {
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
String paramName = parameter.getParameterAnnotation(RequestParam.class).name();
return StringUtils.hasText(paramName);
}
else {
return true;
}
}
else {
// @RequestPart注解不支持
if (parameter.hasParameterAnnotation(RequestPart.class)) {
return false;
}
parameter = parameter.nestedIfOptional();
// 支持解析MultipartFile类型和Part类型
if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
return true;
}
else if (this.useDefaultResolution) {
// 支持解析简单的类型,如基本类型、String类型、Number类型等等
return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
}
else {
return false;
}
}
}
HandlerMethodArgumentResolverComposite:
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); // 获取解析器
if (resolver == null) {
throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]");
}
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); /* 进行参数解析 */
}
AbstractNamedValueMethodArgumentResolver:
public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
/* 获取给定方法参数的命名值 */
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
MethodParameter nestedParameter = parameter.nestedIfOptional();
// 解析注解的name属性值,可能包含占位符和表达式
Object resolvedName = resolveStringValue(namedValueInfo.name);
if (resolvedName == null) {
throw new IllegalArgumentException(
"Specified name must not resolve to null: [" + namedValueInfo.name + "]");
}
/* 将给定的参数类型和值名称解析为参数值 */
Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
if (arg == null) {
if (namedValueInfo.defaultValue != null) {
// 解析并使用默认参数值
arg = resolveStringValue(namedValueInfo.defaultValue);
}
else if (namedValueInfo.required && !nestedParameter.isOptional()) {
// 设置required=true但参数值为null,则根据参数和请求对象抛出不同的异常
handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
}
/* 处理null值 */
arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
}
else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
// 如果参数值是空字符串并且默认值不为null,则解析并使用默认值
arg = resolveStringValue(namedValueInfo.defaultValue);
}
if (binderFactory != null) {
// 创建并初始化数据绑定器,并调用@InitBinder注解的bindMethod,这里的bindMethod我们在分析解析器初始化过程时看到了它的初始化过程
WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
try {
// 如果需要,则用类型转换器转换参数
arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
}
catch (ConversionNotSupportedException ex) {
throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
namedValueInfo.name, parameter, ex.getCause());
}
catch (TypeMismatchException ex) {
throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
namedValueInfo.name, parameter, ex.getCause());
}
}
// 留给子类实现处理解析后的参数值,默认空实现
handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
return arg;
}
AbstractNamedValueMethodArgumentResolver:
private NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
NamedValueInfo namedValueInfo = this.namedValueInfoCache.get(parameter);
if (namedValueInfo == null) {
namedValueInfo = createNamedValueInfo(parameter); /* 创建NamedValueInfo */
namedValueInfo = updateNamedValueInfo(parameter, namedValueInfo);
this.namedValueInfoCache.put(parameter, namedValueInfo);
}
return namedValueInfo;
}
RequestParamMethodArgumentResolver:
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
RequestParam ann = parameter.getParameterAnnotation(RequestParam.class);
// 获取参数@RequestParam注解对象封装到RequestParamNamedValueInfo中
return (ann != null ? new RequestParamNamedValueInfo(ann) : new RequestParamNamedValueInfo());
}
AbstractNamedValueMethodArgumentResolver:
private Object handleNullValue(String name, Object value, Class<?> paramType) {
if (value == null) {
// 如果传入的参数值null并且参数为Boolean类型,则默认返回false
if (Boolean.TYPE.equals(paramType)) {
return Boolean.FALSE;
}
// 如果参数类型为基本类型,抛出异常
else if (paramType.isPrimitive()) {
throw new IllegalStateException("Optional " + paramType.getSimpleName() + " parameter '" + name +
"' is present but cannot be translated into a null value due to being declared as a " +
"primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
}
}
return value;
}
参数解析并处理好之后,下面就是调用过程:
InvocableHandlerMethod:
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 获取bridge方法反射执行
return getBridgedMethod().invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
assertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
throw new IllegalStateException(getInvocationErrorMessage(text, args), ex);
}
catch (InvocationTargetException ex) {
Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
}
else if (targetException instanceof Error) {
throw (Error) targetException;
}
else if (targetException instanceof Exception) {
throw (Exception) targetException;
}
else {
String text = getInvocationErrorMessage("Failed to invoke handler method", args);
throw new IllegalStateException(text, targetException);
}
}
}
下面是handler目标方法的调用和返回结果的处理:
ServletInvocableHandlerMethod:
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 这里的调用过程在分析Model的初始化时已经分析过,不再重复
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// 根据@ResponseStatus注解的内容设置响应状态,@ResponseStatus注解是用来设置响应状态码和错误提示信息给出提示的
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
try {
/* 处理返回值 */
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
}
throw ex;
}
}
HandlerMethodReturnValueHandlerComposite:
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 选择合适的返回值处理器,这里会忽略掉异步返回值处理器
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
/* 处理返回值 */
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
我们之前看到了返回值处理器的注册过程,这里选择合适的返回值处理器也就是在注册的这个集合中选择,我们以ViewNameMethodReturnValueHandler为例来看它如何处理返回值:
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 处理字符序列类型的返回值,当然也包括String类型
if (returnValue instanceof CharSequence) {
String viewName = returnValue.toString();
mavContainer.setViewName(viewName); // 设置视图名称
// 判断是否是重定向视图并设置标记,判断依据就是是否有redirect:前缀或者用户自己配置的匹配模式
if (isRedirectViewName(viewName)) {
mavContainer.setRedirectModelScenario(true);
}
}
else if (returnValue != null){
throw new UnsupportedOperationException("Unexpected return type: " +
returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
}
}
到这里,调用HandlerAdapter对请求的处理就完成了。我们用了大篇幅来分析RequestMappingHandlerAdapter对请求处理的过程,下面我们回到主流程,下面是对拦截器postHandle方法的调用:
HandlerExecutionChain:
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv); // 调用拦截器的postHandle方法
}
}
}
最后是对转发结果的加工:
DispatcherServlet:
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);
/* HandlerExceptionResolver处理异常 */
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
if (mv != null && !mv.wasCleared()) {
/* 根据视图跳转页面 */
render(mv, request, response);
if (errorView) {
// 如果是异常视图处理完成之后将之前曝光的异常信息从request对象中移除掉
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()) {
return;
}
if (mappedHandler != null) {
// 拦截器afterCompletion方法的调用
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
DispatcherServlet:
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
ModelAndView exMv = null;
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
// 遍历注册的HandlerExceptionResolver集合来处理本次异常请求
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
if (exMv != null) {
if (exMv.isEmpty()) {
request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
return null;
}
if (!exMv.hasView()) {
exMv.setViewName(getDefaultViewName(request));
}
if (logger.isDebugEnabled()) {
logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
}
// 将错误的异常信息放入request属性中
WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
return exMv;
}
throw ex;
}
在用户不指定HandlerExceptionResolver的情况下,Spring默认为我们注册了三个HandlerExceptionResolver,AnnotationMethodHandlerExceptionResolver、ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver,它们的应用就是在这里,具体的处理逻辑在这里就不多赘述了,感兴趣的读者可以自行研究,最后我们来看视图的跳转:
DispatcherServlet:
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 国际化处理,如果用户没有指定LocaleResolver,Spring默认为我们注册了AcceptHeaderLocaleResolver来处理国际化
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
if (mv.isReference()) {
/* 解析视图名称 */
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
/* 视图渲染 */
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
getServletName() + "'", ex);
}
throw ex;
}
}
DispatcherServlet:
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
HttpServletRequest request) throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
/* 遍历注册的视图解析器集合解析视图 */
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
在用户不指定ViewResolver的情况下,Spring为我们注册了InternalResourceViewResolver作为默认的视图解析器,我们来看它如何解析视图:
AbstractCachingViewResolver:
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (!isCache()) {
/* 没有缓存直接创建视图 */
return createView(viewName, locale);
}
else { // 尝试从缓存中获取
Object cacheKey = getCacheKey(viewName, locale);
View view = this.viewAccessCache.get(cacheKey);
if (view == null) {
synchronized (this.viewCreationCache) {
view = this.viewCreationCache.get(cacheKey);
if (view == null) {
view = createView(viewName, locale); // 缓存中没有获取到同样要创建
if (view == null && this.cacheUnresolved) {
view = UNRESOLVED_VIEW;
}
if (view != null) {
this.viewAccessCache.put(cacheKey, view);
this.viewCreationCache.put(cacheKey, view);
if (logger.isTraceEnabled()) {
logger.trace("Cached view [" + cacheKey + "]");
}
}
}
}
}
return (view != UNRESOLVED_VIEW ? view : null);
}
}
UrlBasedViewResolver:
protected View createView(String viewName, Locale locale) throws Exception {
// 判断当前ViewResolver是否能够处理当前视图,如果不能返回null继续遍历下一个ViewResolver来处理
if (!canHandle(viewName, locale)) {
return null;
}
// 视图名称以redirect:为前缀的处理
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
view.setHosts(getRedirectHosts());
return applyLifecycleMethods(viewName, view);
}
// 视图名称以forward:为前缀的处理
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
return new InternalResourceView(forwardUrl);
}
/* 否则调用父类的方法来创建视图 */
return super.createView(viewName, locale);
}
AbstractCachingViewResolver:
protected View createView(String viewName, Locale locale) throws Exception {
return loadView(viewName, locale); /* 加载视图 */
}
UrlBasedViewResolver:
protected View loadView(String viewName, Locale locale) throws Exception {
/* 构建视图 */
AbstractUrlBasedView view = buildView(viewName);
View result = applyLifecycleMethods(viewName, view);
return (view.checkResource(locale) ? result : null);
}
InternalResourceViewResolver:
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
/* 调用父类方法构建视图 */
InternalResourceView view = (InternalResourceView) super.buildView(viewName);
if (this.alwaysInclude != null) {
view.setAlwaysInclude(this.alwaysInclude);
}
view.setPreventDispatchLoop(true);
return view;
}
UrlBasedViewResolver:
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
// 拼接前缀后缀
view.setUrl(getPrefix() + viewName + getSuffix());
String contentType = getContentType();
if (contentType != null) {
// 设置contentType
view.setContentType(contentType);
}
view.setRequestContextAttribute(getRequestContextAttribute());
view.setAttributesMap(getAttributesMap());
Boolean exposePathVariables = getExposePathVariables();
if (exposePathVariables != null) {
view.setExposePathVariables(exposePathVariables);
}
Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes();
if (exposeContextBeansAsAttributes != null) {
view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes);
}
String[] exposedContextBeanNames = getExposedContextBeanNames();
if (exposedContextBeanNames != null) {
view.setExposedContextBeanNames(exposedContextBeanNames);
}
return view;
}
解析视图过后,接下来就是视图的渲染:
AbstractView:
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
" and static attributes " + this.staticAttributes);
}
// 创建一个包含动态值和静态属性的组合输出映射,动态值优先于静态属性
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
prepareResponse(request, response);
/* 视图跳转 */
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
在构建视图的时候我们看到以forward:为前缀的视图名称会返回InternalResourceView对象,以redirect:为前缀的视图会返回RedirectView对象,其他情况也同样会返回InternalResourceView对象,我们以InternalResourceView为例来分析视图跳转过程:
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 曝光model中的对象到request属性中
exposeModelAsRequestAttributes(model, request);
exposeHelpers(request);
// 获取转发路径并检查循环转发
String dispatcherPath = prepareForRendering(request, response);
// 获取servlet的请求转发器
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
if (rd == null) {
throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
"]: Check that the corresponding file exists within your web application archive!");
}
if (useInclude(request, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.include(request, response);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.forward(request, response); // 转发
}
}
到这里整个SpringMVC的流程就结束了,篇幅较长,请大家耐心阅读,相信您一定会有所收获。