说到SpringMVC,我们就需要了解一下Handler,HandlerAdapter,HandlerMapping。
- Handler一般都是我们写的带有@Controller的注解的类,或者是带有@RequestMapping的方法(也就是说,一个Servlet请求可以交给一个Bean处理,也可以交给一个方法处理),Spring会把这个Bean或者方法封装成Handler,放进容器
- HandlerAdapter就是使用Handler执行,你可以把它理解成一个工人,Handler就是工具,工人拿工具做工作
- HandlerMapping是一个可以快速地查找Handler的类,一般getHandler返回的是HandlerExecutionChain,它是Handler加Interceptor的集合。
今天就来聊聊SpringMVC中HandlerMapping的实现,以及它的几个子类
HandlerMapping
他只有一个getHandler方法
通过request返回HandlerExecutionChain
它的实现是 AbstractHandlerMapping
AbstractHandlerMapping
是HandlerMapping的实现,大概的定义了HandlerMapping的整体功能
它的getHandler方法如下
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// getHandlerInternal只是模板方法,需要子类去实现
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 = obtainApplicationContext().getBean(handlerName);
}
// 添加拦截器
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
也就是说找Handler的过程是交给子类去完成,而添加拦截器Interceptor则是自己完成
AbstractHandlerMapping的两个重要子类: 是AbstractUrlHandlerMapping和AbstractHandlerMethodMapping
AbstractUrlHandlerMapping
主要是通过类来封装成Handler
直接继承的子类有:
1. SimpleUrlHandlerMapping:通过配置文件直接注册
2. AbstractDetectingUrlHandlerMapping:通过遍历Spring容器的Bean的beanName,解析出对应的url,然后把url跟Handler放进Map中,具体实现类是BeanNameUrlHandlerMapping
AbstractHandlerMethodMapping
主要是通过方法来封装成Handler的,我们常用的就是这个比如@RequestMapping的方法就会被封装成Handler
存放Handler也是Map类型的,但它的Key键是一个类——RequestCondition,它是用来匹配Handler的条件的类,比如请求类型(get,post等),请求参数,头部header,url地址等。通过RequestCondition才能获得Handler,也就是说Map的存放类型为
Map<RequestCondition, Handler>
但是RequestCondition只是一个接口,实现类一般是RequestMappingInfo。
实现类有:
RequestMappingInfoHandlerMapping
RequestMappingHandlerMapping
最后看张图总结一下:
HandlerMapping的实现肯定不止这几个类,我也是初学者,如果有错请大家指出