`

spring源码学习系列3.2-handlerAdapter执行

阅读更多
DispatcherServlet#doDispatch中调用HandlerAdapter来真正执行用户定义的业务逻辑,即controller层代码

//1 获取handlerAdapter
// Determine handler adapter for the current request.
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

//2 执行handlerAdapter.handle
// 以UserController extends MultiActionController extends AbstractController extends WebContentGenerator为例
// Actually invoke the handler.
					mv = ha.handle(processedRequest, response, mappedHandler.getHandler());


DispatcherServlet#getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (logger.isTraceEnabled()) {
				logger.trace("Testing handler adapter [" + ha + "]");
			}
// 1.1 判断handlerAdapter是否适合处理该处理器
			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一般只用到一种(ps:这个地方是否可以优化),以下以SimpleControllerHandlerAdapter为例

适配器模式-对象适配器模式:-委托关系
在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。
https://zh.wikipedia.org/wiki/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F


SimpleControllerHandlerAdapter#support
public boolean supports(Object handler) {
// 1.1.1 判断处理器是否是Controller实例,如果是则返回该handler
		return (handler instanceof Controller);
	}


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

//2.1 调用Controller接口的handleRequest-面向接口编程
		return ((Controller) handler).handleRequest(request, response);
	}



AbstractController#handleRequest
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws Exception {

		// Delegate to WebContentGenerator for checking and preparing.
		checkAndPrepare(request, response, this instanceof LastModified);

		// Execute handleRequestInternal in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					return handleRequestInternal(request, response);
				}
			}
		}

		return handleRequestInternal(request, response);
	}



MultiActionController#handleRequestInternal
@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		try {
//解析方法参数如method=?
			String methodName = this.methodNameResolver.getHandlerMethodName(request);
//根据方法名称,反射调用实例方法
			return invokeNamedMethod(methodName, request, response);
		}
		catch (NoSuchRequestHandlingMethodException ex) {
			return handleNoSuchRequestHandlingMethod(ex, request, response);
		}
	}


MultiActionController#invokeNamedMethod
protected final ModelAndView invokeNamedMethod(
			String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception {

//获取方法执行体,handlerMethodMap在构造函数里面初始化
		Method method = this.handlerMethodMap.get(methodName);
		if (method == null) {
			throw new NoSuchRequestHandlingMethodException(methodName, getClass());
		}

		try {
//设置方法参数(处理方法前面2个必须是request和response)
			Class[] paramTypes = method.getParameterTypes();
			List<Object> params = new ArrayList<Object>(4);
			params.add(request);
			params.add(response);

			if (paramTypes.length >= 3 && paramTypes[2].equals(HttpSession.class)) {
				HttpSession session = request.getSession(false);
				if (session == null) {
					throw new HttpSessionRequiredException(
							"Pre-existing session required for handler method '" + methodName + "'");
				}
				params.add(session);
			}

//根据request设置command对象属性,如果有的话-VS-模型驱动
			// If last parameter isn't of HttpSession type, it's a command.
			if (paramTypes.length >= 3 &&
					!paramTypes[paramTypes.length - 1].equals(HttpSession.class)) {
				Object command = newCommandObject(paramTypes[paramTypes.length - 1]);
				params.add(command);
				bind(request, command);
			}

// 调用方法
			Object returnValue = method.invoke(this.delegate, params.toArray(new Object[params.size()]));
			return massageReturnValueIfNecessary(returnValue);
		}
		catch (InvocationTargetException ex) {
			// The handler method threw an exception.
			return handleException(request, response, ex.getTargetException());
		}
		catch (Exception ex) {
			// The binding process threw an exception.
			return handleException(request, response, ex);
		}
	}

handlerMethodMap在初始化时缓存起来


springmvc 如何根据request设置command对象?



参考:
How to perform Spring validation in MultiActionController?
https://stackoverflow.com/questions/2744587/how-to-perform-spring-validation-in-multiactioncontroller
分享到:
评论

相关推荐

    dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb-redis, dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb-redis整合.zip

    dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb-redis, dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb-redis整合

    spring-3.2-web.jar

    spring-3.2-web.jar

    拓薪教育-Spring内幕深入剖析和实战精讲

    拓薪教育-spring3.2-序【】02.拓薪教育-Spring3.2-介绍IOC上【】03.拓薪教育-spring3.2-介绍IOC下【】04.拓薪教育-spring3.2-AOP和其他功能介绍【】05.拓薪教育-spring3.2-环境搭建【】06.拓薪教育-s 资源太大,传...

    dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb-redis:dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb-redis整合

    core 服务提供者模块lidong-dubbo-web 服务消费者模块mybatis-generator mybatis生成mapper的模块#该项目使用到的技术dubbo2.5spring4mybastis3.2springmvc4spring-data-mongodbspring-data-redisspring-session...

    spring-3.2-core.jar

    spring-3.2-core.jar

    spring-framework-3.2.x-for-eclipse.rar

    本文将针对《spring-framework-3.2.x-for-eclipse.rar》这个压缩包文件,详细介绍如何在Eclipse开发环境中搭建Spring 3.2.x源码分析环境,并探讨其中的关键知识点。 首先,我们来看标题中的"spring-framework-3.2.x...

    spring-3.2-persistence.jar

    spring-3.2-persistence.jar

    spring-3.2-aop.jar

    spring-3.2-aop.jar

    spring3.2-api.chm

    spring3.2-api.chm格式,本人在网上找了好多chm格式的,都不正常现在,没有办法自己找了一个工具打包成chm格式

    spring-context-3.2.xsd

    spring-context-3.2.xsd

    spring v3.2源码

    spring3.2的源代码,至于为什么要下载spring3.2的源代码呢? 个人觉得spring3.2的源代码比较好编译,没啥脾气,像我之前下载的spring的最新版本源代码,还有spring4.0的源代码,不论是使用jdk1.6还是1.7甚至是1.8编译...

    spring-3.2-lib

    标题“spring-3.2-lib”表明这是一组与Spring框架3.2版本相关的库文件。Spring是一个广泛使用的Java企业级应用开发框架,它提供了一种模块化的方式来构建应用程序,支持依赖注入、AOP(面向切面编程)、MVC(模型-...

    spring-beans-3.2.xsd

    spring-beans-3.2.xsd

    spring3.2 源码 jar包

    在本压缩包中,你将获得Spring 3.2版本的源码jar包,这对于开发者来说是一个宝贵的资源,可以深入理解Spring的工作原理,提高代码调试和优化的能力。 首先,让我们来了解一下Spring 3.2的主要特性: 1. **依赖注入...

    Spring-Data-MongoDB3.2

    **Spring Data MongoDB 3.2 整合指南** 在当今的软件开发中,Spring框架以其强大的功能和灵活性深受开发者喜爱,而MongoDB作为一款非关系型数据库,因其高性能、高可扩展性和灵活的数据模型,成为了大数据和实时...

    gradle-3.2-rc-1.zip

    Gradle-3.2-rc-1是Gradle的3.2版本的Release Candidate 1,这意味着这是一个接近正式发布版的测试版本,开发者可以在这个版本上进行最后的测试和验证,确保所有功能稳定后再推出正式版。RC1通常包含了所有计划中的新...

    spring3.2源码-官方原版.zip

    总的来说,Spring 3.2源码的学习可以帮助开发者深入了解Spring框架的工作机制,提高代码设计和维护的能力。结合官方原版的帮助文档,可以更有效地掌握和运用这些知识,从而在实际项目中发挥更大的价值。

    3.2版本Spring源码需要源码所需要的jar:spring-asm-repack-5.0.4.jar,spring-cglib-repack-3.1.jar

    标题中提到的"3.2版本Spring源码需要源码所需要的jar:spring-asm-repack-5.0.4.jar, spring-cglib-repack-3.1.jar",这两部分是Spring源码构建过程中不可或缺的依赖。Spring-asm-repack和Spring-cglib-repack是...

    springmvc4.1+spring4.1+mybatis3.2+spring-security3.2的maven环境搭建

    在"baseArch"这个文件夹中,可能包含了项目的基本架构,包括pom.xml文件、Spring配置文件(如applicationContext.xml、spring-servlet.xml)、MyBatis的Mapper接口和XML配置、Spring Security的配置文件,以及可能的...

Global site tag (gtag.js) - Google Analytics