`
TimerBin
  • 浏览: 358620 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HandlerMapping(1) handler 查找

阅读更多

文章环境说明:

       spring mvc 版本3.2.4.RELEASE,项目中注解方式注册Controller。

 

      众所周知Spring Mvc 中的DispatcherServlet中会使用HandlerMapping 将请求Url解析成为handler处理器。

关于HandlerMapping 实际只有两个突出的功能注册查找。由于注册是在spring容器加载时就已将Controller的每一个方法注册成handler,学起来门槛较高。因此此文将先说查找反推出注册。

注:由于Spring Mvc 的版本不同所以相应代码存在出入,以下代码全部出于spring Mvc 3.2.4.RELEASE。

 

查找

    在DispatcherServlet中doDispatch方法中可以看到根据request使用HandlerMapping获取HandlerExecutionChain对象。代码如下所示:

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 {
                        //在spring-servlet中是否配有MultipartResolver用于解析特殊
                       
 
			//的request 比如附件上传:CommonsMultipartResolver
                        processedRequest = checkMultipart(request);
			multipartRequestParsed = processedRequest != request;
			// Determine handler for the current request.
                        //根据request 在HandlerMapping 查找handler信息
			mappedHandler = getHandler(processedRequest, false);
                        .....
                }catch (Exception ex) {
			dispatchException = ex;
		}
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}catch (Exception ex) {
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	}catch (Error err) {
		triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
	}finally {
		if (asyncManager.isConcurrentHandlingStarted()) {
			// Instead of postHandle and afterCompletion
			mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
			return;
		}
		// Clean up any resources used by a multipart request.
		if (multipartRequestParsed) {
			cleanupMultipart(processedRequest);
		}
	}
}

   DispatcherServlet中的getHandler代码如下所示:

 

@Deprecated
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
	return getHandler(request);
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
 
       //handlerMappings 在容器启动时就已经将handlerMapping进行了赋值
       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;
}

    关于handlerMappings 的赋值代码同样在DispatcherServlet代码中,代码如下所示

  
protected void initStrategies(ApplicationContext context) {
	initMultipartResolver(context);
	initLocaleResolver(context);
	initThemeResolver(context);
	//初始化handlerMapping
	initHandlerMappings(context);
	initHandlerAdapters(context);
	initHandlerExceptionResolvers(context);
	initRequestToViewNameTranslator(context);
	initViewResolvers(context);
	initFlashMapManager(context);
}
private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;
		//可在Web.xml进行显示指定,默认是true 是否默认加载所有HandlerMapping下的values
		if (this.detectAllHandlerMappings) {
			// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
			//获取context中的所有HandlerMappings的子类,并将其下的values 初始化到handlerMappings中
			//其中的子类有
			//RequestMappingHandlerMapping(所有使用注解定义的Controller)
			//BeanNameUrlHandlerMapping(配置文件中定义的Interceptor)
			//SimpleUrlHandlerMapping(配置文件中的mvc:resources显示定义的)
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
				// We keep HandlerMappings in sorted order.
				OrderComparator.sort(this.handlerMappings);
			}
		}else {
			try {
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}
		// Ensure we have at least one HandlerMapping, by registering
		// a default HandlerMapping if no other mappings are found.
		if (this.handlerMappings == null) {
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
			if (logger.isDebugEnabled()) {
				logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
			}
		}
}
 至于在DispatcherServlet的getHandler调用的hm.getHandler()方法就比较简单,在RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping类中并没有对其父类AbstractHandlerMapping的getHandler方法进行重写。其AbstractHandlerMapping的getHandler方法如下所示(spring MVC升级中对并未对此方法进行修改):
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    //此段代码只会在controller是注解方式定义的时候使用到
	Object handler = getHandlerInternal(request);
	//如果在注解中没有查到相应Handler 取默认defaultHandler 
	if (handler == null) {
		handler = getDefaultHandler();
	}
	if (handler == null) {
		return null;
	}
	// Bean name or resolved handler?
	//当handler是String类型时直接从Contest容器中查找
	if (handler instanceof String) {
		String handlerName = (String) handler;
		handler = getApplicationContext().getBean(handlerName);
	}
	return getHandlerExecutionChain(handler, request);
}
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    //将handler转换为HandlerExecutionChain对象
	HandlerExecutionChain chain =
		(handler instanceof HandlerExecutionChain) ?
			(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);
    //将拦截器放到HandlerExecutionChain 处理器中此处的拦截器继承自HandlerInterceptor
	chain.addInterceptors(getAdaptedInterceptors());
    //将拦截器放到HandlerExecutionChain 处理器中此处的拦截器继承自MappedInterceptor
	String lookupPath = urlPathHelper.getLookupPathForRequest(request);
	for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
		if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
			chain.addInterceptor(mappedInterceptor.getInterceptor());
		}
	}
	return chain;
}
 关于getHandlerInternal()方法,只在其子类AbstractHandlerMethodMapping<T>对其进行了实现。由于AbstractHandlerMethodMapping 此类较复杂,将于后续文章对其补充说明!
 
 
 

 

 

分享到:
评论

相关推荐

    SpringMVC入门级教程,免费下载

    2. DispatcherServlet 调用 HandlerMapping 查找并确定处理器 Handler。 3. HandlerMapping 返回 Handler 给 DispatcherServlet。 4. DispatcherServlet 使用 HandlerAdapter 来执行 Handler。 5. Handler 完成业务...

    sprigmvc图文总结

    2、前端控制器请求处理器映射器(HandlerMapping)去查找处理器(Handler)。 3、找到以后处理器映射器(HandlerMappering)向前端控制器返回执行链(HandlerExecutionChain)。 HANDLEREXECUTIONCHAIN,即处理处理...

    spring-ext-handler-mapping.rar_ext_spring ext_spring mvc

    1. **扩展Spring HandlerMapping** Spring MVC默认提供了一些内置的HandlerMapping实现,如BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping等。但是,在实际项目中,我们可能需要根据特定需求定制自己的映射...

    SpringMVC框架1

    HandlerMapping可以根据XML配置或注解来查找与请求匹配的Handler。这允许开发者通过多种方式灵活地定义请求处理规则。 接着,HandlerMapping返回找到的Handler给DispatcherServlet。Handler通常是实现了特定接口...

    springmvc框架基础知识学习笔记.docx

    2. 处理器映射器(HandlerMapping):根据请求的 URL 或其他条件(如注解)来查找合适的处理器(Handler),即 Controller。它允许开发者定义多种映射策略,例如基于注解的映射或基于 XML 配置的映射。 3. 处理器...

    SpringMVC源码解读之HandlerMapping

    在Spring MVC框架中,`HandlerMapping`是核心组件之一,它的主要职责是将HTTP请求映射到合适的处理器(Handler)。这个过程涉及到请求的分发、拦截器的管理以及控制器的查找。本文将深入探讨`HandlerMapping`的工作...

    SpringMVC源码解读之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化

    在Spring MVC框架中,HandlerMapping是一个至关重要的组件,它的职责是将HTTP请求映射到相应的处理器(Handler)。在源码解读中,我们关注的是AbstractDetectingUrlHandlerMapping,这是一个抽象类,它通过扫描应用...

    muyinchen#woker#springmvc学习笔记(4)-前端控制器1

    1.前端控制器接收请求 2.前端控制器调用HandlerMapping(处理器映射器)根据url查找Handler 3.调用处理器适配器执行Handler,得到

    springMVC的生命周期详解

    在第二步中,DispatcherServlet会请求HandlerMapping(处理器映射器)来查找对应的Handler。HandlerMapping可以根据xml配置、注解进行查找。 第三步:处理器映射器HandlerMapping向前端控制器返回Handler 在第三步...

    springMVC基础原理

    2. **分发请求**:DispatcherServlet 根据配置的 HandlerMapping 查找并选择合适的 Handler 来处理该请求。 3. **执行 Handler**:找到合适的 Handler 后,由 HandlerAdapter 负责调用 Handler,执行具体的业务逻辑...

    spring-mvc 程序结构以及调用流程

    2. DispatcherServlet根据请求信息调用HandlerMapping来查找对应的Controller处理器。 3. HandlerMapping找到对应的Controller后,返回给DispatcherServlet。 4. DispatcherServlet调用HandlerAdapter来执行...

    spring mvc工作流程

    - **匹配 Handler**:`DispatcherServlet` 使用 `HandlerMapping` 来查找与当前请求 URL 匹配的 Handler。如果找到,则返回一个包含 Handler 和 Interceptor 信息的 `HandlerExecutionChain` 对象。 - **适配 ...

    SpringMVC讲解文档

    * 根据 URL 查找相应的 Handler 处理器 * 可以通过 XML 配置方式或注解方式实现 HandlerAdapter 处理器适配器 * 根据特定规则执行 Handler 处理器 * 需要按照 HandlerAdapter 的要求编写 Handler Handler 处理器 ...

    SpringMVC课堂笔记(2)

    HandlerMapping则根据URL查找对应的Handler。在SpringMVC中,HandlerMapping可以通过XML配置或注解方式来实现。HandlerAdapter是适配器模式的体现,它确保了不同类型的Handler可以按照统一的规则执行。Handler是...

    SpringMVC.pdf

    2. DispatcherServlet调用HandlerMapping查找Handler(Controller)。 3. DispatcherServlet将请求发送至Handler。 4. Handler处理请求后返回ModelAndView。 5. DispatcherServlet将ModelAndView传给ViewResolver...

    传智播客_Springmvc+Mybatis由浅入深全套视频教程-SpringMVC笔记(两天)

    2. DispatcherServlet请求HandlerMapping查找处理器(Handler)。 3. HandlerMapping向前端控制器返回Handler。 4. 前端控制器调用处理器适配器(HandlerAdapter)去执行Handler。 5. 处理器适配器执行Handler,...

    Spring源代码解析(四):Spring_MVC.doc

    如果`detectAllHandlerMappings`配置为true(如代码第2行所示),则会查找并加载所有HandlerMapping。如果配置为false(第13行之后的代码),则只会尝试获取名为`HANDLER_MAPPING_BEAN_NAME`的特定bean,如果没有...

    SpringMVC源码解读之HandlerMapping - AbstractUrlHandlerMapping系列request分发

    在Spring MVC框架中,HandlerMapping是负责将HTTP请求映射到相应的处理器(Handler)的核心组件。AbstractUrlHandlerMapping是HandlerMapping的一个抽象实现,它处理基于URL的请求分发。本文将深入探讨...

    Java Spring MVC面试题

    2. 处理器映射器 HandlerMapping:根据请求的URL来查找Handler。 3. 处理器适配器 HandlerAdapter:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler...

    跟我学SpringMVC

    - **请求处理过程**:接收请求 -&gt; 查找合适的Handler -&gt; 调用HandlerAdapter执行Handler -&gt; 处理返回值 -&gt; 渲染视图。 ##### 2. Handler **Handler**即控制器,用于处理特定的HTTP请求。可以是接口控制器,也可以...

Global site tag (gtag.js) - Google Analytics