springmvc之如何扫描controller以及⽣效
⼀、前⾔
上⼀篇⽂章介绍了SpringMVC的请求过程,其中在DispatcherServlet中的 doDispatch⽅法中,说到了根据 request 查具体Handler 的,这篇⽂章主要介绍 Handler的查,即为怎么根据Request 请求URL查到 Controller 。
⼆、查Handler
2.1、回顾 doDispatch
1.
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
try {
/
/ Determine handler for the current request.
//根据 request 查Handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
}catch (Exception ex) {
dispatchException = ex;
}
}catch (Exception ex) {
mvc的controller
}catch (Throwable err) {
}finally {
}
}
2.2、查看 getHandler⽅法
1.
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = Handler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
根据源码可知,getHandler起始返回的是 HandlerExecutionChain,其实是在 handlerMappings中查的,那handlerMappings⼜是从哪来的呢,接下来分析 handlerMappings的出处。
2.3、handlerMappings的前世今⽣
上篇⽂章中结束Dispatcher的初始化时介绍到了,在DispatcherServlet的 onRefresh ⽅法中调⽤了 initHandlerMappings ⽅法,接下来看看initHandlerMappings⽅法的实现逻辑。
1.
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
// 在SpringContext的容器中查 HandlerMapping 接⼝的所有实例。如果查询到进⾏排序
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}else {
try {
HandlerMapping hm = Bean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}catch (NoSuchBeanDefinitionException ex) {
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isTraceEnabled()) {
"': using default strategies from DispatcherServlet.properties");
}
}
}
查看看 handlerMappings中的HandlerMapper,如下图所⽰,其中主要解析Controller是在 RequestMappingHandlerMapping中。
接下来看看 HandlerMapping 类的实现结构
接下来重点看HandlerMapping的实现类, RequestMappingHandlerMapping 类。
1、先查看下ReqeustMappingHandlerMapping类的继承关系图
根据继承关系图可知,RequestMappingHandlerMapping同时实现了 InitializingBean和ApplicationContextAware两个接⼝,熟悉这两个接⼝的都知道,其中InitializingBean 的⽅法 afterPropertiesSet 是在类初始化完成且设置属性完成后调⽤,那么接下来看
看 RequestMappingHandlerMapping对afterPropertiesSet的实现。
1.
public void afterPropertiesSet() {
//⽤调⽤了⽗类的⽅法
super.afterPropertiesSet();
}
此实现中除了设置⼀下参数配置,⼜调⽤了⽗类的afterPropertiesSet的实现,在看看⽗类的⽅法1.