1. 程式人生 > >Spring原始碼解讀之Spring MVC HandlerMapping元件(二)

Spring原始碼解讀之Spring MVC HandlerMapping元件(二)

一、HandlerMapping

HandlerMapping作用是根據request找到相應的處理器Handler和Interceptors,並將Handler和Interceptors封裝成HandlerExecutionChain 物件返回。HandlerMapping接口裡面只有一個方法。
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
HandlerMapping繼承結構如下圖:
在這裡插入圖片描述
可以看到HandlerMapping家族的成員分兩支,一支繼承AbstractUrlHandlerMapping,另一支繼承AbstractHandlerMethodMapping,而這兩支都繼承自抽象類AbstractHandlerMapping。

1.1 AbstractHandlerMapping

AbstractHandlerMapping是HandlerMapping的抽象實現,所有HandlerMapping都繼承自AbstractHandlerMapping。AbstractHandlerMapping採用的是模板方法的設計模式,具體的演算法由子類去完成。
來看一下主要的方法 getHandler()

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		//根據request獲取handler,具體由子類實現
		Object handler = getHandlerInternal(request);
		//找不到handler就獲取預設的Handler
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// handler是bean name情況下,在Spring容器上下文根據該name檢索
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}
		// 這裡將檢索到的Handler和Interceptors封裝到HandlerExecutionChain 物件中
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
		//省略
		....
		return executionChain;
	}

可以看出getHandlerInternal方法是抽象方法,由子類實現。接下來看一下getHandlerExecutionChain方法。

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
      //將handler設定到HandlerExecutionChain 中
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
		
		// 裝配Interceptor
		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;
	}

這個方法也非常簡單,首先使用handler創建出HandlerExcutionChain型別的變數,然後將adaptedInterceptors和符合要求的mappedInterceptors新增進去,最後將其返回。AbstracthandlerMapping中儲存了所用配置的Interceptor,在獲取到Handler後會自己根據從Request提取的lookupPath將相應的Interceptors裝配上去,當然子類也可以通過getHandlerInternal方法設定自己的Interceptor。

1.2AbstractUrlHandlerMapping

未完待續。。。