在研究源码的时候,我们应该从最高层来看,所以我们先看这个接口的定义:
package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; /**1.定义一个将请求和处理器进行映射的接口。开发人员也可以自己实现这个接口,虽然这是不必须的,因为现在的springmvc中已经提供了大量的实现,最典型的就是BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping,RequestMappingHandlerMapping等等,以前的版本中,如果我们没有显示的设置的话那么就是前面的两个RequestMapping,但是现在的版本是BeanNameUrlHandlerMapping,DefaultAnnotationHandlerMapping这两个,配置了mvc:annotation-driven注解的话 就是RequestMappingHandlerMapping)2.在映射的结果中可以包括0或多个的拦截器,在执行处理器的前面会先执行preHandle,如果拦截器都返回true的时候,才会执行处理器的逻辑同时处理参数的能力也是非常的强大的,我们可以定义RequestMapping处理各种参数(但是明显不用这样做的,我们可以直接定义参数转化器) 3.因为系统可以设置多个的HandlerMapping,所以我们应该实现Ordered这个接口,表示个各自的优先级,越小优先级越高。默认是Integer.MAX_VALUE.优先级是最低的*/ public interface HandlerMapping { //这个属性表示的是url对应的HandlerMapping String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping"; //这个request匹配度最高的HanlderMapping String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern"; //是否支持类级别的映射 像我们的DefaultAnnotationHandlerMapping就使用了这个属性来表示支持类级别的。(如果我们没有设置的话,默认就是支持的 //@see AnnotationMethodHandlerAdapter$ServletHandlerMethodResolver.useTypeLevelMapping()) String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping"; //也是request中的KEY名称,值时map,存放在的是键值对 String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables"; //和上面差不多,但是类别有一些不同 存放的是Matrix Variable(就是值可以用;分割的那个) String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables"; //HandlerMapping支持的媒体类型 String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes"; /** 这个这个类的唯一一个方法,根据职责单一原则,我们就明白了,HandlerMapping的唯一职责就是将一个请求根据不同的策略 最终转化为HandlerExecutionChain这样的一个对象,这里不是一个接口,而是一个类,这个类就是封装了处理器和一系列的 拦截器,并且代理了这一系列处理的的前置和后置处理 */ HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; }
通过上面的分析已经大概明白了HandlerMapping的目的,他的目的就是一个请求来了以后,我们需要通过HandlerMapping来构造一个执行后续操作的环境,这里面包括我们定义的支持媒体类型,随请求来的各种参数,系统中设置的拦截器等等。如果要我说,这一步相当于springmvc的入口吧。
我们再看一个基础的抽象类,这个类就是就是提供了一些基本的设施,留下一个主要的工作给子类来进行实现,这是个是AbstractHandlerMapping。因为这个很多的方法,我并不会将类贴出来,主要分析一下这个类实现了哪些的功能,以及我们关注点在哪里,扩展在哪里。
这个抽象类不仅实现了HandlerMapping,而且实现了Ordered接口,这个接口在HandlerMapping中提示了我们就是定义自己的顺序。并且继承了spring的基础设置类,来提供一些ServletContext和WebApplicationContext这些的引用。所以,如果我们要实现自己的HandlerMapping的话,还是建议这个抽象类就OK了。
我们看最主要的一个方法:
@Override public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } return getHandlerExecutionChain(handler, request); }
其实getHandlerInternal(...)是一个模板方法,让子类来返回处理器,如果是空的话,那么就返回默认的处理器.但是如果我们想要自己设置默认的处理器的话,我们要自己注入。默认是null。如果我们提供了一个string类型的处理器,他会去当前的容器中查找处理器,很奇怪的是,我发现子类中也做了这样的一件事==!,而且这代码还是同一个哥们写的。看来大神的思想我们还是不太懂呢。还有最后的getHandlerExecutionChai非常的重要,拦截器都是在这个方法里面获取到的. 除了这些重要的点,这个抽象类还留了一个子:extendInterceptors(List<Object> interceptors) 留给子类对拦截器做一些操作。
接下来就是对每一种不同类型的HandlerMapping的不同处理了,但是归根结底还是返回HandlerExecutionChain,里面包括了处理器,拦截器等