欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring5 源码阅读笔记(5.2.3)handle

程序员文章站 2022-03-06 08:09:56
...

类 HandlerAdapter

@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

类 AbstractHandlerMethodAdapter

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

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

跟 handleInternal:

@Nullable
protected abstract ModelAndView handleInternal(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;

跟 handleInternal:

@Override
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 {
		//Controller里面具体方法调用,重点看
		// 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);
		}
	}

跟 invokeHandlerMethod:
类 RequestMappingHandlerAdapter

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

	ServletWebRequest webRequest = new ServletWebRequest(request, response);
	try {
		//获取数据绑定工厂  @InitBinder注解支持,没太多用
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
		//Model工厂,收集了@ModelAttribute注解的方法
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

		//可调用的方法对象
		ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
		if (this.argumentResolvers != null) {
			//设置参数解析器
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		}
		if (this.returnValueHandlers != null) {
			//设置返回值解析器
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
		}
		//设置参数绑定工厂
		invocableMethod.setDataBinderFactory(binderFactory);
		//设置参数名称解析类
		invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
		
		//每次请求都会new一个mavContainer 
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
		mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
		//调用有@ModelAttribute注解的方法。每次请求都会调用有@ModelAttribute注解的方法
		//把@ModelAttribute注解的方法的返回值存储到 ModelAndViewContainer对象的map中了
		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();
			LogFormatUtils.traceDebug(logger, traceOn -> {
				String formatted = LogFormatUtils.formatValue(result, !traceOn);
				return "Resume with async result [" + formatted + "]";
			});
			invocableMethod = invocableMethod.wrapConcurrentResult(result);
		}

		//Controller方法调用,重点看看
		invocableMethod.invokeAndHandle(webRequest, mavContainer);
		if (asyncManager.isConcurrentHandlingStarted()) {
			return null;
		}

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

跟 invokeAndHandle:
类 ServletInvocableHandlerMethod

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
		Object... providedArgs) throws Exception {

	//具体调用逻辑,重点看  见 5.2.3.1
	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 {
		//返回值处理                见 5.2.3.2
		this.returnValueHandlers.handleReturnValue(
				returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
	catch (Exception ex) {
		if (logger.isTraceEnabled()) {
			logger.trace(formatErrorForReturnValue(returnValue), ex);
		}
		throw ex;
	}
}

5.2.3.1 invokeForRequest

类 InvocableHandlerMethod

@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
		Object... providedArgs) throws Exception {

	//获取参数数组,重点看
	Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
	if (logger.isTraceEnabled()) {
		logger.trace("Arguments: " + Arrays.toString(args));
	}
	return doInvoke(args);
}

跟 getMethodArgumentValues:

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
		Object... providedArgs) throws Exception {

	if (ObjectUtils.isEmpty(getMethodParameters())) {
		return EMPTY_ARGS;
	}
	//入参的包装类,里面包装了参数类型,参数名称,参数注解等等信息
	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] = findProvidedArgument(parameter, providedArgs);
		if (args[i] != null) {
			continue;
		}
		//典型的策略模式,根据parameter能否找到对应参数的处理类,能找到就返回true
		if (!this.resolvers.supportsParameter(parameter)) {
			throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
		}
		try {
			//具体参数值解析过程,重点看看
			args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
		}
		catch (Exception ex) {
			// Leave stack trace for later, exception may actually be resolved and handled..
			if (logger.isDebugEnabled()) {
				String error = ex.getMessage();
				if (error != null && !error.contains(parameter.getExecutable().toGenericString())) {
					logger.debug(formatArgumentError(parameter, error));
				}
			}
			throw ex;
		}
	}
	return args;
}

跟 resolveArgument:

@Override
@Nullable
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
		NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

	//根据参数获取对应参数的解析类
	HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
	if (resolver == null) {
		throw new IllegalArgumentException(
				"Unsupported parameter type [" + parameter.getParameterType().getName() + "]." +
						" supportsParameter should be called first.");
	}
	//策略模式去调用具体参数解析类
	return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}

跟 resolveArgument:
类 HandlerMethodArgumentResolver
Spring5 源码阅读笔记(5.2.3)handle
重点看类 AbstractNamedValueMethodArgumentResolver
它的 resolveArgument 用来处理 @Pathvariable 、@RequestParam

@Override
@Nullable
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
		NativeWebRequest webRequest, @Nullable 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 + "]");
	}

	//传入占位符的值,从webRequest里找到
	Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
	if (arg == null) {
		if (namedValueInfo.defaultValue != null) {
			arg = resolveStringValue(namedValueInfo.defaultValue);
		}
		else if (namedValueInfo.required && !nestedParameter.isOptional()) {
			handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
		}
		arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
	}
	else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
		arg = resolveStringValue(namedValueInfo.defaultValue);
	}

	if (binderFactory != null) {
		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;
}

5.2.3.2 handleReturnValue

类 HandlerMethodReturnValueHandlerComposite

@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
		ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
	//找到能够处理的handler
	HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
	if (handler == null) {
		throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());}
	handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}

跟 handleReturnValue:
类 HandlerMethodReturnValueHandler
Spring5 源码阅读笔记(5.2.3)handle
类 RequestResponseBodyMethodProcessor
处理 @Responsebody

@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
		ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
		throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

	mavContainer.setRequestHandled(true);
	ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
	ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

	// Try even with null return value. ResponseBodyAdvice could get involved.
	writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
相关标签: # MVC