spring MVC源码解析

spring MVC源码解析

1、前端控制器的架构?

在这里插入图片描述

可知springmvc处理请求的核心方法就是doDispatch()方法

2.前端控制器的核心方法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 {
                //1、检查是否文件上传请求
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				
                //2、根据当前的请求地址找到那个类能来处理;拿到执行链
				mappedHandler = getHandler(processedRequest);
                
                //3、如果没有找到哪个处理器(控制器)能处理这个请求就404,或者抛异常
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				
                //4、拿到能执行这个类的所有方法的适配器;(反射工具AnnotationMethodHandlerAdapter)
				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;
					}
				}

                //执行所有拦截器的preHandle
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

                //控制器(Controller),处理器(Handler)
                //5、适配器来执行目标方法;将目标方法执行完成后的返回值作为视图名,设置保存到ModelAndView中
                //目标方法无论怎么写,最终适配器执行完成以后都会将执行后的信息封装成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);
			}
            //转发到目标页面;
            //6、根据方法最终执行完成后封装的ModelAndView;转发到对应页面,而且ModelAndView中的数据可以从请求域中获取
			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);
				}
			}
		}
	}

总结DispatcherServlet流程

1.、所有请求过来DispatcherServlet收到请求,

2.、调用doDispatch()方法进行处理

​ 1、getHandler():根据当前请求地址找到能处理这个请求的目标处理器类(处理器)

​ 根据当前请求在HandlerMapping中找到这个请求的映射信息,获取到目标处理器类

​ 2、getHandlerAdapter():根据当前处理器类获取到能执行这个处理器方法的适配器;

​ 根据当前处理器类,找到当前类的HandlerAdapter(适配器)

​ 3.、使用刚才获取到的适配器(AnnotationMethodHandlerAdapter )执行目标方法;

​ 4.、目标方法执行后会返回一个ModelAndView对象

​ 5.、根据ModelAndView的信息转发到具体的页面,并可以在请求域中取出ModelAndView中的模型数据

第一检查是否是文件上传这里就不细讲了,知道有这个流程就行

重点是这个getHandler(processedRequest)方法 : 根据当前请求地址找到能处理这个请求的目标处理器类(处理器)

3.获取Handle(处理器):getHandler(processedRequest) 方法

源码

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
         
		if (this.handlerMappings != null) {
		    //遍历 HandlerMapping 通过请求路径找到Handel
			for (HandlerMapping hm : this.handlerMappings) {
				if (logger.isTraceEnabled()) {
					logger.trace(
							"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
				}
				// 获取拦截器的执行链(下面细说这个方法)
				HandlerExecutionChain handler = hm.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

getHandler()会返回目标处理器类的执行链;HandelExecutionChain

HandlerMapping 处理器映射:他里面保存了每一个处理器能处理哪些请求的映射信息;

handlerMap:ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HandlerMapping的handlerMap属性中;

下一次请求过来,就来看哪个HandlerMapping中有这个请求映射信息就行了;

3.获取HandleAdpter(处理器适配器):getHandlerAdapter(mappedHandler.getHandler()) 方法

源码

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
		    //遍历handlerAdapters  判断当前的处理器适配器是否支持这个handler
			for (HandlerAdapter ha : this.handlerAdapters) {
				if (logger.isTraceEnabled()) {
					logger.trace("Testing handler adapter [" + ha + "]");
				}
				//是否支持
				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");
	}

拿HandlerAdapter适配器去执行目标方法

处理方法的具体执行流程

4.handle(processedRequest, response, mappedHandler.getHandler())

源码

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}

这里会跳转执行handleInternal(request, response, (HandlerMethod) handler) 方法

4.1:handleInternal(request, response, (HandlerMethod) handler)

源码

protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		ModelAndView mav;
		checkRequest(request);

		// 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);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}

由上源码知道 真正执行的方法又跳到了 mav = invokeHandlerMethod(request, response, handlerMethod)

4.2.nvokeHandlerMethod(request, response, handlerMethod)

源码

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
	        //创建了一个数据绑定的工厂 
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			//将model与binderFactory进行一下 绑定
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

            //创建了一个方法执行器-->执行方法
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			if (this.argumentResolvers != null) {
			    //设置参数解析器
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			if (this.returnValueHandlers != null) {
			    //设置HandlerMethod的返回值解析器
				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			}
			//将方法执行器与binderFactory进行一下 绑定
			invocableMethod.setDataBinderFactory(binderFactory);
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

            //创建ModelAndViewContainer 称之为隐含模型  
			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			//初始化操作
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

            //下面都是对异步调用的一些设置
			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()) {
				return null;
			}

			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

4.3.invocableMethod.invokeAndHandle(webRequest, mavContainer);

源码

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        //又又又跳转了
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		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);
		Assert.state(this.returnValueHandlers != null, "No return value handlers");
		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;
		}
	}
4.4.invokeForRequest(webRequest, mavContainer, providedArgs)

源码

public Object invokeForRequest(NativeWebRequest request, @Nullable 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;
	}
4.4.1参数获取: Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs)

源码

private Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable 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;
			}
			//获取能解析出方法参数值的参数解析器
			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.getExecutable().toGenericString() +
						": " + getArgumentResolutionErrorMessage("No suitable resolver for", i));
			}
		}
		return args;
	}
4.4.1获取方法参数解析器:this.argumentResolvers.supportsParameter(parameter)

源码

public boolean supportsParameter(MethodParameter parameter) {
        //跳转了
		return (getArgumentResolver(parameter) != null);
	}
4.4.2这个方法真正获取方法参数解析器:HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter)

源码

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() + "]");
				}
				//检查当前你遍历的参数解析器是否支持当前参数的解析,支持就存入参数解析器的缓存中
				if (methodArgumentResolver.supportsParameter(parameter)) {
					result = methodArgumentResolver;
					//放到缓存中
					this.argumentResolverCache.put(parameter, result);
					break;
				}
			}
		}
		return result;
	}

}
4.4.3检查当前参数解析器是否支持解析当前数:supportsParameter(MethodParameter parameter)

源码

@Override
	public boolean supportsParameter(MethodParameter parameter) {
	    //方法的参数中是否有RequestParam注解。
		if (parameter.hasParameterAnnotation(RequestParam.class)) {
		    //参数是否是 Map类型的
			if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
				RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
				return (requestParam != null && StringUtils.hasText(requestParam.name()));
			}
			else {
				return true;
			}
		}
		else {
		    //如果有RequestPart注解,直接返回faslse
			if (parameter.hasParameterAnnotation(RequestPart.class)) {
				return false;
			}
			parameter = parameter.nestedIfOptional();
			//是否是文件上传中的值
			if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
				return true;
			}
			//
			else if (this.useDefaultResolution) {
			    //判断是否是简单类型参数
				return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
			}
			else {
				return false;
			}
		}
	}

在上面的代码中我们可以看到,请求对应的处理方法的中的参数如果带有RequestParam注解,则判断是不是Map类型的参数,如果不是,则直接返回true。

如果没有RequestParam注解,则判断如果有RequestPart注解,则直接返回false,接着判断是否是文件上传表单中的参数值,如果不是,则接着判断useDefaultResolution是否为true。

这里需要说明一下的是: argumentResolvers中有两个RequestParamMethodArgumentResolver bean, 一个useDefaultResolution为false,一个useDefaultResolution为true。当useDefaultResolution为false的bean是用来处理RequestParam注解的,useDefaultResolution为true的bean是用来处理简单类型的bean的。在我们这个例子中,useDefaultResolution的值为true。那么接下来回判断是不是简单类型参数,我们进到BeanUtils.isSimpleProperty这个方法中看一下:

4.4.4BeanUtils.isSimpleProperty(parameter.getNestedParameterType())

源码

	public static boolean isSimpleProperty(Class<?> clazz) {
		Assert.notNull(clazz, "Class must not be null");
		return isSimpleValueType(clazz) || (clazz.isArray() &&                  isSimpleValueType(clazz.getComponentType()));
	}
4.4.5:isSimpleValueType()

源码

	public static boolean isSimpleValueType(Class<?> clazz) {
		return (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() ||
				CharSequence.class.isAssignableFrom(clazz) ||
				Number.class.isAssignableFrom(clazz) ||
				Date.class.isAssignableFrom(clazz) ||
				URI.class == clazz || URL.class == clazz ||
				Locale.class == clazz || Class.class == clazz);
	}

真正进行类型判断的方法是isSimpleValueType这个方法,如果请求对应处理类的方法的参数为 枚举类型、String类型、Long、Integer、Float、Byte、Short、Double、Date、URI、URL、Locale、Class、文件上传对象或者参数是数组,数组类型为上面列出的类型则返回true。即 我们的请求对应处理类的方法的参数为:枚举类型、String类型、Long、Integer、Float、Byte、Short、Double、Date、URI、URL、Locale、Class、文件上传对象或者参数是数组,数组类型为上面列出的类型,则请求参数处理类为:RequestParamMethodArgumentResolver。我们先看一下RequestParamMethodArgumentResolver的UML类图关系:

4.4.6:上面都是对参数解析器的获取:接下看看参数时怎么解析的resolveArgument()

源码

	@Override
	public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		//获取请求对应处理方法的参数字段值
		NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
		MethodParameter nestedParameter = parameter.nestedIfOptional();
		//解析之后的请求对应处理方法的参数字段值
		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);
		//如果从请求中得到的参数值为null的话
		if (arg == null) {
			//判断是否有默认值
			if (namedValueInfo.defaultValue != null) {
				arg = resolveStringValue(namedValueInfo.defaultValue);
			}//判断这个字段是否是必填,RequestParam注解默认为必填。
			else if (namedValueInfo.required && !nestedParameter.isOptional()) {
				handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
			}//处理null值
			arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
		}//如果为得到的参数值为null,且有默认的值
		else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
			arg = resolveStringValue(namedValueInfo.defaultValue);
		}
		//参数的校验
		if (binderFactory != null) {
			//参数校验
		}
		//空实现
		handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
 
		return arg;
	}
4.4.7NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);

源码

	private NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
	    //先从缓存中获取
		NamedValueInfo namedValueInfo = this.namedValueInfoCache.get(parameter);
		//缓存中不存在这个值
		if (namedValueInfo == null) {
		    //创建NamedValueInfo对象
			namedValueInfo = createNamedValueInfo(parameter);
			//更新刚才得到的NamedValueInfo对象
			namedValueInfo = updateNamedValueInfo(parameter, namedValueInfo);
			//放入缓存中
			this.namedValueInfoCache.put(parameter, namedValueInfo);
		}
		return namedValueInfo;
	}

5.处理方法的执行:Object returnValue = doInvoke(args)

源码

protected Object doInvoke(Object... args) throws Exception {
        //设置反射允许的权限
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
		    //反射的方式方法执行
			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) {
			// Unwrap for HandlerExceptionResolvers ...
			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);
			}
		}
	}
5.1.getBridgedMethod().invoke(getBean(), args)

源码

public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }
        //方法执行
        return ma.invoke(obj, args);
    }
5.2.ma.invoke(obj, args)
public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
        //跳转
        return this.delegate.invoke(var1, var2);
    }
5.3.this.delegate.invoke(var1, var2)

源码

public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
        if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
            MethodAccessorImpl var3 = (MethodAccessorImpl)(new MethodAccessorGenerator()).generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());
            this.parent.setDelegate(var3);
        }
        //执行目标方法
        return invoke0(this.method, var1, var2);
    }
5.4.invoke0(this.method, var1, var2) 此处就执行目标方法了—>测试的方法

在这里插入图片描述

目标测试方法执行跳转不必深究,此处只是记录过程,知道是用反射的方式执行 目标方法就行

重点是参数的设置Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);

在执行目标方法前设置好好方法执行需要的参数列表

6.返回ModelAadView :getModelAndView()

源码

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

		modelFactory.updateModel(webRequest, mavContainer);
		if (mavContainer.isRequestHandled()) {
			return null;
		}
		ModelMap model = mavContainer.getModel();
		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
		if (!mavContainer.isViewReference()) {
			mav.setView((View) mavContainer.getView());
		}
		if (model instanceof RedirectAttributes) {
			Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
			HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
			if (request != null) {
				RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
			}
		}
		return mav;
	}

无论你处理方法中返回的什么,在源码底层都是给你返回给你一个ModelAndView—>根据ModelAndView用viewResolver解析返回一个View–>view 对数据进行渲染,请求转发

6.1.视图解析:processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException)

源码

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable 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);
				mv = processHandlerException(request, response, handler, exception);
				errorView = (mv != null);
			}
		}

		// Did the handler return a view to render?
		//ModelAndView mv 不为null开始视图解析
		if (mv != null && !mv.wasCleared()) {
		    //渲染页面
			render(mv, request, response);
			if (errorView) {
				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()) {
			// Concurrent handling started during a forward
			return;
		}

		if (mappedHandler != null) {
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}
6.1.1:方法进渲染页面请求转发:render(mv, request, response);

源码

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		//国际化的时区解析器,了解
		Locale locale =
				(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		View view;
		//获取返回为String的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() + "'");
			}
		}
		else {
			// No need to lookup: the ModelAndView object contains the actual View object.
			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() + "'");
			}
		}

		// Delegate to the View object for rendering.
		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;
		}
	}
6.1.1.1:view = resolveViewName(viewName, mv.getModelInternal(), locale, request);

源码

protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
			Locale locale, HttpServletRequest request) throws Exception {

		if (this.viewResolvers != null) {
			for (ViewResolver viewResolver : this.viewResolvers) {
			    //使用视图解析器解析返回View
				View view = viewResolver.resolveViewName(viewName, locale);
				if (view != null) {
					return view;
				}
			}
		}
		return null;
	}
6.1.1.1.1:视图解析器解析返回 视图:viewResolver.resolveViewName(viewName, locale);

源码

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) {
						// Ask the subclass to create the View object.
						//创建视图
						view = createView(viewName, locale);
						if (view == null && this.cacheUnresolved) {
							view = UNRESOLVED_VIEW;
						}
						if (view != null) {
					        //将创建好的View 存储到缓存中
							this.viewAccessCache.put(cacheKey, view);
							this.viewCreationCache.put(cacheKey, view);
							if (logger.isTraceEnabled()) {
								logger.trace("Cached view [" + cacheKey + "]");
							}
						}
					}
				}
			}
			return (view != UNRESOLVED_VIEW ? view : null);
		}
	}
6.1.1.1.1.1.1:view = this.viewCreationCache.get(cacheKey);

源码

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());
			//创建 "redirect:/..." 重定向的RedirectView
			RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
			String[] hosts = getRedirectHosts();
			if (hosts != null) {
				view.setHosts(hosts);
			}
			return applyLifecycleMethods(viewName, view);
		}
		// Check for special "forward:" prefix.
		if (viewName.startsWith(FORWARD_URL_PREFIX)) {
			String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
			创建 "forward:/..." 请求转发InternalResourceView
			return new InternalResourceView(forwardUrl);
		}
		// Else fall back to superclass implementation: calling loadView.
		//创建其他类型的View-->里面细节感兴趣的可用自己去看看
		return super.createView(viewName, locale);
	}

上面过程已经得到了一个View对象:下面执行View的render()方法 渲染要输出给页面的所有数据

返回View对象;

1、视图解析器得到View对象的流程就是,所有配置的视图解析器都来尝试根据视图名(返回值)得到View(视图)对象;如果能得到就返回,得不到就换下一个视图解析器;

2、调用View对象的render方法;

6.1.2:view.render(mv.getModelInternal(), request, response)

源码

public void render(@Nullable 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 保存所有数据
		Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
		prepareResponse(request, response);
		//渲染要给页面输出的所有数据
		renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
	}
6.3.1:renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);

源码

protected void renderMergedOutputModel(
			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		// Expose the model object as request attributes.
		//将模型Map model中的数据放在请求域中
		exposeModelAsRequestAttributes(model, request);

		// Expose helpers as request attributes, if any.
		exposeHelpers(request);

		// Determine the path for the request dispatcher.
		//确定请求调度程序的路径。
		String dispatcherPath = prepareForRendering(request, response);

		// Obtain a RequestDispatcher for the target resource (typically a JSP).
		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 already included or response already committed, perform include, else forward.
		if (useInclude(request, response)) {
			response.setContentType(getContentType());
			if (logger.isDebugEnabled()) {
				logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
			}
			rd.include(request, response);
		}

		else {
			// Note: The forwarded resource is supposed to determine the content type itself.
			if (logger.isDebugEnabled()) {
				logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
			}
			//实际请求转发
			rd.forward(request, response);
		}
	}

视图解析器只是为了得到视图对象;视图对象才能真正的转发(将模型数据全部放在请求域中)或者重定向到页面

视图对象才能真正的渲染视图;

7.DispatcherServlet 九大组件

源码

/** Well-known name for the MultipartResolver object in the bean factory for this namespace. */
    //文件上传解析器
	public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";

	/** Well-known name for the LocaleResolver object in the bean factory for this namespace. */
	//区域信息解析器;和国际化有关
	public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";

	/** Well-known name for the ThemeResolver object in the bean factory for this namespace. */
	//主体解析器 强大的主题效果更换
	public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";

	/**
	 * Well-known name for the HandlerMapping object in the bean factory for this namespace.
	 * Only used when "detectAllHandlerMappings" is turned off.
	 * @see #setDetectAllHandlerMappings
	 */
	 //处理器映射器 通过处理器映射器-->找到 处理器Handler
	public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";

	/**
	 * Well-known name for the HandlerAdapter object in the bean factory for this namespace.
	 * Only used when "detectAllHandlerAdapters" is turned off.
	 * @see #setDetectAllHandlerAdapters
	 */
	//处理器适配器-->通过处理器找到处理器适配器,用 是配置去执行处理方法
	public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";

	/**
	 * Well-known name for the HandlerExceptionResolver object in the bean factory for this namespace.
	 * Only used when "detectAllHandlerExceptionResolvers" is turned off.
	 * @see #setDetectAllHandlerExceptionResolvers
	 */
	 //处理异常解析器
	public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";

	/**
	 * Well-known name for the RequestToViewNameTranslator object in the bean factory for this namespace.
	 */
	 //ViewResolver是根据ViewName查找VIew,但有的Handler处理完后并没有设置View也没有ViewName,这时需要从request获        取viewName,RequestToViewNameTranslator就是做这个事情。
	 //RequestToViewNameTranslator在SpringMVC容器中只可以配置一个,所有request到ViewName的转换规则都要在一个             Translator里面全部实现。
	public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";

	/**
	 * Well-known name for the ViewResolver object in the bean factory for this namespace.
	 * Only used when "detectAllViewResolvers" is turned off.
	 * @see #setDetectAllViewResolvers
	 */
	 //视图解析器
	public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";

	/**
	 * Well-known name for the FlashMapManager object in the bean factory for this namespace.
	 */
	 //FlashMap+Manager:SpringMVC中运行重定向携带数据的功能
	public static final String FLASH_MAP_MANAGER_BEAN_NAME = "flashMapManager";
7.1:九大组件的初始化

源码

protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}

组件初始化具体细节博主就不写了–>要吐血了

组件的初始化:

有些组件在容器中是使用类型找的,有些组件是使用id找的;

去容器中找这个组件,如果没有找到就用默认的配置;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值