springmvc九大组件之HandlerAdapter详解

 更新时间:2023年11月18日 08:48:49   作者:morris131  
这篇文章主要介绍了springmvc九大组件之HandlerAdapter详解,RequestMappingHandlerAdapter支持的handler的类型是HandlerMethod,而HandlerMethod是通过解析@RequestMapping注解获得的,需要的朋友可以参考下

HandlerAdapter

HandlerAdapter处理器适配器用来执行Controller中的目标方法,由于上面有三种HandlerMapping,对应这里三种HandlerAdapter:

  • RequestMappingHandlerAdapter:对应RequestMappingHandlerMapping
  • HttpRequestHandlerAdapter:对应SimpleUrlHandlerMapping
  • SimpleControllerHandlerAdapter:对应BeanNameUrlHandlerMapping

当然还有SimpleServletHandlerAdapter负责处理servlet请求,默认不开启,用得少。

RequestMappingHandlerAdapter

根据handler获得HandlerAdapter

RequestMappingHandlerAdapter支持的handler的类型是HandlerMethod,而HandlerMethod是通过解析@RequestMapping注解获得的。

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports

public final boolean supports(Object handler) {
	/**
		 * supportsInternal返回true
		 * @see RequestMappingHandlerAdapter#supportsInternal(org.springframework.web.method.HandlerMethod) 
		 */
	return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

handler的执行

RequestMappingHandlerAdapter通过反射执行HandlerMethod。

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

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...
		// 调用handlerMethod
		mav = invokeHandlerMethod(request, response, handlerMethod);
	}

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

	return mav;
}

将HandlerMethod封装为ServletInvocableHandlerMethod,ServletInvocableHandlerMethod负责真正的方法调用。

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod

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负责真正的方法调用
		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));
		// 处理@ModelAttribute注解
		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();
	}
}

requestHandled为false表示后面还需要进行视图解析,requestHandled为true表示后面不需要进行视图解析,可以直接返回响应。

org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle

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

	// 反射调用controller中的方法
	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;
	}

	// requestHandled用来表示后面是否还需要进行视图解析
	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;
	}
}

先进行参数的解析,然后反射调用controller中的方法:

org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest

	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));
		}
		// 反射调用controller中的方法
		return doInvoke(args);
	}

SimpleControllerHandlerAdapter

SimpleControllerHandlerAdapter主要负责执行类型为Controller的handler,由于handler都实现了Controller接口,只需要调用Controller接口的handleRequest()方法即可。

package org.springframework.web.servlet.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;

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

HttpRequestHandlerAdapter

HttpRequestHandlerAdapter主要负责执行类型为HttpRequestHandler的handler,由于handler都实现了HttpRequestHandler接口,只需要调用Controller接口的handleRequest()方法即可。

package org.springframework.web.servlet.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.lang.Nullable;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;

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

到此这篇关于springmvc九大组件之HandlerAdapter详解的文章就介绍到这了,更多相关HandlerAdapter详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot中操作Redis及工具类的封装详解

    SpringBoot中操作Redis及工具类的封装详解

    在我们项目开发中总是免不了会使用缓存,Redis现在基本是我们公司中非常常见的缓存方案,包括在用户token的缓存,热点信息的缓存等,这篇文章主要讲讲在SpringBoot项目中如何去操作Redis,及最后工具类的封装
    2023-05-05
  • 2020macOS Big Sur配置Java开发环境之jdk安装过程

    2020macOS Big Sur配置Java开发环境之jdk安装过程

    这篇文章主要介绍了2020macOS Big Sur配置Java开发环境之jdk安装,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • Java堆&优先级队列示例讲解(下)

    Java堆&优先级队列示例讲解(下)

    这篇文章主要通过示例详细为大家介绍Java中的堆以及优先级队列,文中的示例代码讲解详细,对我们了解java有一定帮助,需要的可以参考一下
    2022-03-03
  • java高效打印一个二维数组的实例(不用递归,不用两个for循环)

    java高效打印一个二维数组的实例(不用递归,不用两个for循环)

    下面小编就为大家带来一篇java高效打印一个二维数组的实例(不用递归,不用两个for循环)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • 新手学习JQuery基本操作和使用案例解析

    新手学习JQuery基本操作和使用案例解析

    这篇文章主要介绍了新手学习JQuery基本操作和使用案例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java线程编程中Thread类的基础学习教程

    Java线程编程中Thread类的基础学习教程

    这篇文章主要介绍了Java线程编程中Thread类的基础学习教程,Thread类包含诸多操作线程的方法,非常重要,需要的朋友可以参考下
    2015-12-12
  • SpringBoot整合jasypt实现敏感信息的加密详解

    SpringBoot整合jasypt实现敏感信息的加密详解

    一般公司的核心业务代码中,都会存在与数据库、第三方通信的secret key等敏感信息,如果以明文的方式存储,一旦泄露,那将会给公司带来巨大的损失。本篇文章通过讲解:Springboot集成Jasypt对项目敏感信息进行加密,提高系统的安全性
    2022-09-09
  • IDEA2022创建Maven Web项目教程(图文)

    IDEA2022创建Maven Web项目教程(图文)

    本文主要介绍了IDEA2022创建Maven Web项目教程,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 详解spring整合shiro权限管理与数据库设计

    详解spring整合shiro权限管理与数据库设计

    这篇文章主要介绍了详解spring整合shiro权限管理与数据库设计,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 详解Java反射创建对象

    详解Java反射创建对象

    今天带大家学习Java的基础知识,文中对Java反射创建对象作了非常详细的介绍及代码示例,对正在学习Java的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05

最新评论