首页 > 编程语言 >SpringMVC源码-获取HandleAdapter和调用HandleAdapter.handle

SpringMVC源码-获取HandleAdapter和调用HandleAdapter.handle

时间:2022-11-05 21:36:08浏览次数:56  
标签:handle handler Object request mavContainer 源码 return HandleAdapter handlerMethod

DispatcherServlet.getHandlerAdapter(Object handler)

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	if (this.handlerAdapters != null) {
		for (HandlerAdapter adapter : this.handlerAdapters) {
			if (adapter.supports(handler)) {
				return adapter;
			}
		}
	}
	throw new ServletException("No adapter for handler [" + handler +
			"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

如果handlerAdapters不为null,遍历handlerAdapters,如果HandlerAdapter支持处理request,返回HandlerAdapter。handlerAdapters有三个元素,分别是HttpRequestHandlerAdapter,SimpleControllerHandleAdapter,
RequestMappingHandlerAdapter。

一、HttpRequestHandlerAdapter

public class HttpRequestHandlerAdapter implements HandlerAdapter {

@Override
public boolean supports(Object handler) {
	return (handler instanceof HttpRequestHandler);
}

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

	((HttpRequestHandler) handler).handleRequest(request, response);
	return null;
}

@Override
public long getLastModified(HttpServletRequest request, Object handler) {
	if (handler instanceof LastModified) {
		return ((LastModified) handler).getLastModified(request);
	}
	return -1L;
}

}

HttpRequestHandlerAdapter:适配使用通用DispatcherServlet的HttpRequestHandler接口。supports支持处理的handle类型是HttpRequestHandler。处理handle的方法handle()调用HttpRequestHandler.handleRequest,返回的ModelAndView是null。

二、SimpleControllerHandleAdapter

public class SimpleControllerHandlerAdapter implements HandlerAdapter {

@Override
public boolean supports(Object handler) {
	return (handler instanceof Controller);
}

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

	return ((Controller) handler).handleRequest(request, response);
}

@Override
public long getLastModified(HttpServletRequest request, Object handler) {
	if (handler instanceof LastModified) {
		return ((LastModified) handler).getLastModified(request);
	}
	return -1L;
}

}

SimpleControllerHandlerAdapter:适配使用通用DispatcherServlet的Controller工作流接口。supports支持的handle类型是Controller接口。处理handle的handle()方法调用Controller.handleRequest.

三、RequestMappingHandlerAdapter

AbstractHandlerMethodAdapter.supports(Object handler)

public final boolean supports(Object handler) {
	return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

supports支持的handle类型是HandlerMethod。

RequestMappingHandlerAdapter.supportsInternal(HandlerMethod handlerMethod)

protected boolean supportsInternal(HandlerMethod handlerMethod) {
	return true;
}

AbstractHandlerMethodAdapter.handle(HttpServletRequest request, HttpServletResponse response, Object handler)

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

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

RequestMappingHandlerAdapter.handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod)

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

1、checkRequest检查是否支持request的请求方法,request是否需要session。
2、如果synchronizeOnSession为true,获取session后调用invokeHandlerMethod,否则调用invokeHandlerMethod。invokeHandlerMethod执行handle处理方法。
3、设置响应头

RequestMappingHandlerAdapter.invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod)

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

	ServletWebRequest webRequest = new ServletWebRequest(request, response);
	try {
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
		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);

		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();
			LogFormatUtils.traceDebug(logger, traceOn -> {
				String formatted = LogFormatUtils.formatValue(result, !traceOn);
				return "Resume with async result [" + formatted + "]";
			});
			invocableMethod = invocableMethod.wrapConcurrentResult(result);
		}

		invocableMethod.invokeAndHandle(webRequest, mavContainer);
		if (asyncManager.isConcurrentHandlingStarted()) {
			return null;
		}

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

1、创建ServletWebRequest
2、获取WebDataBinderFactory
3、获取ModelFactory
4、创建ServletInvocableHandlerMethod,并设置argumentResolvers,returnValueHandlers,WebDataBinderFactory,parameterNameDiscoverer等属性
5、创建ModelAndViewContainer并添加所有输入FlashMap的值,调用initModel
6、创建AsyncWebRequest并设置Timeout属性
7、创建WebAsyncManager并设置属性
8、判断WebAsyncManager是否有ConcurrentResult,如果有则获取ConcurrentResult
9、invokeAndHandle执行实际handle处理方法
10、获取ModelAndView并返回

RequestMappingHandlerAdapter.getDataBinderFactory(HandlerMethod handlerMethod)

private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
	Class<?> handlerType = handlerMethod.getBeanType(); //@Controller标注的class类型
	Set<Method> methods = this.initBinderCache.get(handlerType);
	if (methods == null) {
		methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
		this.initBinderCache.put(handlerType, methods);
	}
	List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
	// Global methods first
	this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
		if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
			Object bean = controllerAdviceBean.resolveBean();
			for (Method method : methodSet) {
				initBinderMethods.add(createInitBinderMethod(bean, method));
			}
		}
	});
	for (Method method : methods) {
		Object bean = handlerMethod.getBean();
		initBinderMethods.add(createInitBinderMethod(bean, method));
	}
	return createDataBinderFactory(initBinderMethods);
}

1、获取@Controller标注的Class类型
2、通过第一步得到的bean类型查找@InitBinder注解的方法并设置到initBinderCache中。
3、遍历initBinderAdviceCache,如果ControllerAdviceBean需要处理bean,则将controllerAdviceBean要处理的bean和controllerAdviceBean的method封装成InvocableHandlerMethod后设置initBinderArgumentResolvers和webBindingInitializer加入initBinderMethods集合。
4、遍历第二步得到的method集合,将bean和method装成InvocableHandlerMethod后设置initBinderArgumentResolvers和webBindingInitializer加入initBinderMethods集合。
5、createDataBinderFactory创建WebDataBinderFactory。

RequestMappingHandlerAdapter.getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory)

private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
	SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
	Class<?> handlerType = handlerMethod.getBeanType();
	Set<Method> methods = this.modelAttributeCache.get(handlerType);
	if (methods == null) {
		methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
		this.modelAttributeCache.put(handlerType, methods);
	}
	List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
	// Global methods first
	this.modelAttributeAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
		if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
			Object bean = controllerAdviceBean.resolveBean();
			for (Method method : methodSet) {
				attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
			}
		}
	});
	for (Method method : methods) {
		Object bean = handlerMethod.getBean();
		attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
	}
	return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
}

1、获取SessionAttributesHandler
2、获取@Controller标注的Class类型
3、通过第二步得到的bean类型查找@ModelAttribute注解的方法并设置到modelAttributeCache中。
4、遍历modelAttributeAdviceCache,如果ControllerAdviceBean需要处理bean,则将controllerAdviceBean要处理的bean和controllerAdviceBean的method封装成InvocableHandlerMethod后设置argumentResolvers和WebDataBinderFactory加入attrMethods集合。
5、遍历第三步得到的method集合,将bean和method装成InvocableHandlerMethod后设置argumentResolvers和WebDataBinderFactory加入attrMethods集合。

ModelFactory.initModel(NativeWebRequest request, ModelAndViewContainer container, HandlerMethod handlerMethod)

public void initModel(NativeWebRequest request, ModelAndViewContainer container, HandlerMethod handlerMethod)
		throws Exception {

	Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
	container.mergeAttributes(sessionAttributes);
	invokeModelAttributeMethods(request, container);

	for (String name : findSessionAttributeArguments(handlerMethod)) {
		if (!container.containsAttribute(name)) {
			Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
			if (value == null) {
				throw new HttpSessionRequiredException("Expected session attribute '" + name + "'", name);
			}
			container.addAttribute(name, value);
		}
	}
}

1、ModelAndViewContainer合并sessionAttributesHandler属性值
2、invokeModelAttributeMethods调用ModelAttribute方法填充Model。
3、查找@SessionAttributes的方法参数并将值设置到ModelAndViewContainer

ModelFactory.invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container)

private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container)
		throws Exception {

	while (!this.modelMethods.isEmpty()) {
		InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();
		ModelAttribute ann = modelMethod.getMethodAnnotation(ModelAttribute.class);
		Assert.state(ann != null, "No ModelAttribute annotation");
		if (container.containsAttribute(ann.name())) {
			if (!ann.binding()) {
				container.setBindingDisabled(ann.name());
			}
			continue;
		}

		Object returnValue = modelMethod.invokeForRequest(request, container);
		if (modelMethod.isVoid()) {
			if (StringUtils.hasText(ann.value())) {
				if (logger.isDebugEnabled()) {
					logger.debug("Name in @ModelAttribute is ignored because method returns void: " +
							modelMethod.getShortLogMessage());
				}
			}
			continue;
		}

		String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());
		if (!ann.binding()) {
			container.setBindingDisabled(returnValueName);
		}
		if (!container.containsAttribute(returnValueName)) {
			container.addAttribute(returnValueName, returnValue);
		}
	}
}

1、从modelMethods集合中选取元素并获取InvocableHandlerMethod,获取@ModelAttribute属性,如果@ModelAttribute不需要绑定将@ModelAttribute的name添加到bindingDisabled集合。否则执行invokeForRequest
2、获取getNameForReturnValue返回值名称
3、将返回值名为key,返回值为value添加到ModelAndViewContainer中。

ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,Object... providedArgs)

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()) {
			disableContentCachingIfNecessary(webRequest);
			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(formatErrorForReturnValue(returnValue), ex);
		}
		throw ex;
	}
}

1、invokeForRequest执行实际handle处理方法
2、setResponseStatus设置响应状态
3、mavContainer设置requestHandled属性
4、处理返回值

InvocableHandlerMethod.invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs)

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

1、getMethodArgumentValues获取方法参数
2、调用doInvoke执行实际handle处理方法

InvocableHandlerMethod.getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs)

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

	MethodParameter[] parameters = getMethodParameters();
	if (ObjectUtils.isEmpty(parameters)) {
		return EMPTY_ARGS;
	}

	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;
		}
		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 exMsg = ex.getMessage();
				if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
					logger.debug(formatArgumentError(parameter, exMsg));
				}
			}
			throw ex;
		}
	}
	return args;
}

1、获取方法参数
2、遍历方法参数,findProvidedArgument解析providedArgs参数,如果存在则执行下一轮循环。否则执行resolvers.supportsParameter判断是否支持解析参数类型。不支持抛出异常。
3、解析参数

HandlerMethodArgumentResolverComposite.supportsParameter(MethodParameter parameter)

  public boolean supportsParameter(MethodParameter parameter) {
	return getArgumentResolver(parameter) != null;
}

HandlerMethodArgumentResolverComposite.getArgumentResolver(MethodParameter parameter)

	private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
	HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
	if (result == null) {
		for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
			if (resolver.supportsParameter(parameter)) {
				result = resolver;
				this.argumentResolverCache.put(parameter, result);
				break;
			}
		}
	}
	return result;
}

遍历argumentResolvers,判断HandlerMethodArgumentResolver是否支持解析参数,如果支持解析参数则将参数为key,HandlerMethodArgumentResolver为value设置到argumentResolverCache。

HandlerMethodArgumentResolverComposite.resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory)

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

1、获取参数解析器
2、解析参数

没有加注解的非简单类型由ModelAttributeMethodProcessor.resolveArgument解析参数。

HandlerMethodReturnValueHandlerComposite.handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest)

public void handleReturnValue(@Nullable 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);
}

1、选择返回值处理器
2、调用处理器处理返回值

HandlerMethodReturnValueHandlerComposite.selectHandler(@Nullable Object value, MethodParameter returnType)

private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
	boolean isAsyncValue = isAsyncReturnValue(value, returnType);
	for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
		if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
			continue;
		}
		if (handler.supportsReturnType(returnType)) {
			return handler;
		}
	}
	return null;
}

遍历returnValueHandlers,判断HandlerMethodReturnValueHandler是否支持处理返回值类型,如果支持则返回。

标签:handle,handler,Object,request,mavContainer,源码,return,HandleAdapter,handlerMethod
From: https://www.cnblogs.com/shigongp/p/16860923.html

相关文章