SpringMvc源码分析3——HandlerMapping


SpringMvc源码分析3——HandlerMapping

一. 准备

首先再次贴一下HandlerMapping结构图:

HandlerMapping

接着上一篇,我们暴露的接口:

@RestController
public class IndexController {
    @GetMapping("/hello")
    public String hello(String name) {
        return "hello: " + name;
    }
}

bebug到DispatcherServlet#doDispatch

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 1. todo待分析,关注点一
    mappedHandler = getHandler(processedRequest);
    
    // 2. todo待分析,关注点二
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    // 3. todo待分析,关注点三
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    // 4. todo待分析,关注点四
    applyDefaultViewName(processedRequest, mv);
    
    // 5. todo待分析,关注点五
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

}

二. 分析

1. 关注几个属性值

我们先看一下DispatcherServlet内部几个属性此时的值:

/** List of HandlerMappings used by this servlet. */
	@Nullable
	private List<HandlerMapping> handlerMappings;

	/** List of HandlerAdapters used by this servlet. */
	@Nullable
	private List<HandlerAdapter> handlerAdapters;

	/** List of HandlerExceptionResolvers used by this servlet. */
	@Nullable
	private List<HandlerExceptionResolver> handlerExceptionResolvers;

	/** RequestToViewNameTranslator used by this servlet. */
	@Nullable
	private RequestToViewNameTranslator viewNameTranslator;
	
/** List of ViewResolvers used by this servlet. */
	@Nullable
	private List<ViewResolver> viewResolvers;
  • handlerMappings handlerMappings

  • handlerAdapters

  • handlerExceptionResolvers handlerExceptionResolvers

  • viewNameTranslatorviewNameTranslator

  • viewResolversviewResolvers

2. 关注点一源码

mappedHandler = getHandler(processedRequest);

这里主要是根据请求找到匹配的HandlerMapping,然后得到相应的handler和拦截器,封装成HandlerExecutionChain返回。

源码:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
        // todo分析
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

找到的匹配到HandlerMappingRequestMappingHandlerMapping.接着执行:

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  // 得到handler
  Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
	
  	// 获取到请求的拦截器,封装成HandlerExecutionChain返回
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

		return executionChain;
	}

RequestMappingHandlerMapping里面维护着mappingRegistry,它的值为:

其实mappingRegistry属性在AbstractHandlerMethodMapping里面。

mappingRegistry然后根据请求找出里面匹配到的RequestMappingInfo,从而得到HandlerMethod对象。

最后得到的handler为:

handler

之后,获取到请求的拦截器,再封装成HandlerExecutionChain返回。对应代码为:

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

三. 总结

HandlerMapping的作用其实就是请求和具体Handler处理器(这里的Handler一般为Controller里的一个方法method,或者org.springframework.web.servlet.mvc.Controller等)之间的一个映射关系。

SimpleUrlHandlerMapping则是会根据内部维护的urlMap(以路径作为键,并以处理程序bean或bean名称作为值的Map)查找具体的handler

RequestMappingHandlerMapping则会处理请求和注解(@Controller@RequestMapping)方法对应的映射关系。


文章作者: shiv
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 shiv !
评论
  目录