读HandlerMapping子类RequestMappingHandlerMapping源码

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping继承自org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping,后者又继承自org.springframework.web.servlet.handler.AbstractHandlerMethodMapping<T>,再向上看继承关系便到了org.springframework.web.servlet.handler.AbstractHandlerMapping(</span>

AbstractHandlerMapping实现了org.springframework.web.servlet.HandlerMapping和org.springframework.core.Ordered接口,并继承了org.springframework.web.context.support.WebApplicationObjectSupport).


AbstractHandlerMapping

上述描述了RequestMappingHandlerMapping继承体系结构,这里我们重点从AbstractHandlerMethodMapping开始分析,关于更上层次的AbstractHandlerMapping只需要了解这是整个实现了HandlerMapping接口最基础的子类,它实现了HandlerMapping接口的HandlerExecutionChain getHandler(HttpServletRequest request) 方法:

<span style="white-space:pre">	</span>public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
<span style="white-space:pre">		</span>Object handler = getHandlerInternal(request);
<span style="white-space:pre">		</span>if (handler == null) {
<span style="white-space:pre">			</span>handler = getDefaultHandler();
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>if (handler == null) {
<span style="white-space:pre">			</span>return null;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>// Bean name or resolved handler?
<span style="white-space:pre">		</span>if (handler instanceof String) {
<span style="white-space:pre">			</span>String handlerName = (String) handler;
<span style="white-space:pre">			</span>handler = getApplicationContext().getBean(handlerName);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return getHandlerExecutionChain(handler, request);
<span style="white-space:pre">	</span>}
</pre><pre name="code" class="java"><span style="white-space:pre">	</span>protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
<span style="white-space:pre">		</span>HandlerExecutionChain chain =
<span style="white-space:pre">			</span>(handler instanceof HandlerExecutionChain) ?
<span style="white-space:pre">				</span>(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);


<span style="white-space:pre">		</span>chain.addInterceptors(getAdaptedInterceptors());


<span style="white-space:pre">		</span>String lookupPath = urlPathHelper.getLookupPathForRequest(request);
<span style="white-space:pre">		</span>for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
<span style="white-space:pre">			</span>if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
<span style="white-space:pre">				</span>chain.addInterceptor(mappedInterceptor.getInterceptor());
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}


<span style="white-space:pre">		</span>return chain;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;
</pre><p><span style="white-space:pre">	</span>我们看到在getHandler方法里为我们定义了根据request拿到handler对象并封装成HandlerExecutionChain,然后对HandlerExecutionChain初始化Interceptor(包括HandlerInterceptor和MappedInterceptor)<span style="background-color: rgb(255, 255, 255);">,而实际上获取handler的逻辑被委托给了抽象方法getHandlerInternal,由AbstractHandlerMapping的子类来实现。父类定义工作流程,而流程中的具体细节交由子类来实现又一内型的模板模式的应用。</span></p><p><span style="background-color: rgb(255, 255, 255);"></span></p><p><span style="background-color: rgb(255, 255, 255);"><span style="white-space:pre">	<strong>AbstractHandlerMethodMapping<T></strong></span></span></p><p><span style="background-color: rgb(255, 255, 255);"><span style="white-space:pre"><span style="font-weight: bold; white-space: pre;">	</span>分</span>析完了最作了实现HandlerMapping接口最为基础的AbstractHandlerMapping,我们一起来看一下AbstractHandlerMethodMapping,作为AbstractHandlerMapping的子类看看它是如何具体实现我们在上部分分析中提到的抽象方法getHandlerInternal的</span><span style="white-space: pre;">	</span></p><p><span style="white-space: pre;"></span><pre name="code" class="java">  <span style="white-space:pre">	</span>protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
<span style="white-space:pre">		</span>String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
<span style="white-space:pre">		</span>if (logger.isDebugEnabled()) {
<span style="white-space:pre">			</span>logger.debug("Looking up handler method for path " + lookupPath);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
<span style="white-space:pre">		</span>if (logger.isDebugEnabled()) {
<span style="white-space:pre">			</span>if (handlerMethod != null) {
<span style="white-space:pre">				</span>logger.debug("Returning handler method [" + handlerMethod + "]");
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>else {
<span style="white-space:pre">				</span>logger.debug("Did not find handler method for [" + lookupPath + "]");
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
<span style="white-space:pre">	</span>}

<span style="white-space:pre">	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
<span style="white-space:pre">		</span>List<Match> matches = new ArrayList<Match>();
<span style="white-space:pre">		</span>List<T> directPathMatches = this.urlMap.get(lookupPath);
<span style="white-space:pre">		</span>if (directPathMatches != null) {
<span style="white-space:pre">			</span>addMatchingMappings(directPathMatches, matches, request);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>if (matches.isEmpty()) {
<span style="white-space:pre">			</span>// No choice but to go through all mappings...
<span style="white-space:pre">			</span>addMatchingMappings(this.handlerMethods.keySet(), matches, request);
<span style="white-space:pre">		</span>}


<span style="white-space:pre">		</span>if (!matches.isEmpty()) {
<span style="white-space:pre">			</span>Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
<span style="white-space:pre">			</span>Collections.sort(matches, comparator);
<span style="white-space:pre">			</span>if (logger.isTraceEnabled()) {
<span style="white-space:pre">				</span>logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>Match bestMatch = matches.get(0);
<span style="white-space:pre">			</span>if (matches.size() > 1) {
<span style="white-space:pre">				</span>Match secondBestMatch = matches.get(1);
<span style="white-space:pre">				</span>if (comparator.compare(bestMatch, secondBestMatch) == 0) {
<span style="white-space:pre">					</span>Method m1 = bestMatch.handlerMethod.getMethod();
<span style="white-space:pre">					</span>Method m2 = secondBestMatch.handlerMethod.getMethod();
<span style="white-space:pre">					</span>throw new IllegalStateException(
<span style="white-space:pre">							</span>"Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" +
<span style="white-space:pre">							</span>m1 + ", " + m2 + "}");
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>handleMatch(bestMatch.mapping, lookupPath, request);
<span style="white-space:pre">			</span>return bestMatch.handlerMethod;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>else {
<span style="white-space:pre">			</span>return handleNoMatch(handlerMethods.keySet(), lookupPath, request);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}</span>
<span style="white-space:pre">	</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值