转载请注明出处:https://blog.csdn.net/qq_26443737/article/details/90646532
HandlerMapping
HandlerMapping是DispatcherServlet中直接初始化的九大组件之一。HandlerMapping的作用之一是根据request找到相应的处理器Hanlder(比如,一个@RequestMapping就是一个Handler)和Interceptors。HandlerMapping接口里只有一个方法。
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
getHandler返回的永远是一个HandlerExecutionChain类型的对象,包括一个handler和interceptors(如果有的话)。
HandlerMapping的实现类需要注册到Spring MVC的容器中才能使用。注册方式是在配置文件中配置一个Bean,Spring MVC会按照类型将它注册到HandlerMapping中。如果没有在文件中配置,则使用DispatcherServlet默认的配置,在包org.springframework.web.servlet的同名文件DispatcherServlet.properties中。
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.
BeanNameUrlHandlerMapping,org.springframework.web.servlet.mvc
.annotation.DefaultAnnotationHandlerMapping
默认配置的实现类为BeanNameUrlHandlerMapping以及DefaultAnnotationHandlerMapping。
BeanNameUrlHandlerMapping
BeanNameUrlHandlerMapping继承自AbstractDetectingUrlHandlerMapping(注:Spring MVC中类名前缀包含Abstract的基本都是抽象类),它不是HanlerMapping的直接实现,而是与HandlerMapping接口隔了好几个抽象类。
BeanNameUrlHandlerMapping的继承结构如图1。
- 功能分层实现,逻辑清晰
- 每个类实现特定功能的方法,便于维护和理解
- 固定方法之间的调用关系(如,父类设计模板方法交由子类实现,并调用子类的方法)
- 便于代码重用(不需要为实现一个具体子类重写所有的方法)
(注:以上优点为本人心得,无具体参考,谨慎引用。)
下面将简单分析BeanNameUrlHanderMapping的几个父类及相应的作用。
AbstractHandlerMapping
AbstractHandlerMapping是HandlerMapping的抽象实现,另外该抽象类还继承一个类WebApplicationObjectSupport,实现了另外一个接口Ordered。
继承WebApplicationObjectSupport的目的之一是为了在HandlerMapping具体子类创建后进行初始化,调用相应的入口方法获取Servlet中的handlers和interceptors,并将其和对应的url放入指定的map中。
实现Ordered接口是为了对HandlerMapping进行排序,以便在处理具有相同部分的url时,使用合适的HandlerMapping(具体可参考:《看透Spring MVC源代码与实践》 第11章)。
AbstractHandlerMapping在initApplicationcontext()方法(继承WebApplicationObjectSupport的子类会在对象创建后调用该方法)保存所用配置的Interceptors,在获取到Handler后会自己根据从request提取的lookupPath将相应的Interceptors装配上去。
@Override
protectedvoidinitApplicationContext()throwsBeansException{
extendInterceptors(this.interceptors);
detectMappedInterceptors(this.mappedInterceptors);
initInterceptors();
}
AbstractHandlerMapping另外一个重要作用是实现了getHandler(HttpServletRequest request)方法,根据request返回对应的HandlerExcutionChain对象:
@Override
publicfinalHandlerExecutionChaingetHandler(HttpServletRequestrequest
)throwsException{
Objecthandler=getHandlerInternal(request);
if(handler==null){
handler=getDefaultHandler();
}
if(handler==null){
returnnull;
}
//如果handler是String类型,则根据该字符串获取从容器中获取对应的实例
if(handlerinstanceofString){
StringhandlerName=(String)handler;
handler=getApplicationContext().getBean(handlerName);
}
returngetHandlerExecutionChain(handler,request);
}