HandlerMapping 是 spring mvc中一个核心类,其主要功能就是为请求找到合适的处理器,我们编写的controller就是处理器,也是当下最流行的处理器
HandlerMapping的初始化
想要了解HandlerMapping的初始化,首先得了解DispatcherServlet是如何初始化得,有兴趣得话可以看一看 spring mvc 源码解析之 DispatcherServlet
DispatcherServlet在初始化得时候,调用了九大组件得初始化方法,其中就有HandlerMapping
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context); //初始化HandlerMappings
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
initHandlerMappings(context)
/**
* Well-known name for the HandlerMapping object in the bean factory for this namespace.
* Only used when "detectAllHandlerMappings" is turned off.
* @see #setDetectAllHandlerMappings
*/
public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
//detectAllHandlerMappings默认情况下是true,所以大多数情况下是一定会进到这个里面,可以通过set方法设置成false
if (this.detectAllHandlerMappings) {
// 查看ApplicationContext容器中所有得HandlerMapping
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
//HandlerMapping不为空得情况,则对其进行排序
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
//如果detectAllHandlerMappings为false得话,则去查找HANDLER_MAPPING_BEAN_NAME这个常量类型得HandlerMapping
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
//如果以上两种方式还是没有查询到HandlerMapping,那么则获取默认得HandlerMapping
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
for (HandlerMapping mapping : this.handlerMappings) {
if (mapping.usesPathPatterns()) {
this.parseRequestPath = true;
break;
}
}
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
if (defaultStrategies == null) {
try {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
//
// 获取到org.springframework.web.servlet包下DispatcherServlet.properties文件中得org.springframework.web.servlet.HandlerMapping属性
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
}
}
//根据属性值反射创建HandlerMapping
String key = strategyInterface.getName();
String value = defaultStrategies.getProperty(key);
if (value != null) {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<>(classNames.length);
for (String className : classNames) {
try {
Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
catch (ClassNotFoundException ex) {
throw new BeanInitializationException(
"Could not find DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]", ex);
}
catch (LinkageError err) {
throw new BeanInitializationException(
"Unresolvable class definition for DispatcherServlet's default strategy class [" +
className + "] for interface [" + key + "]", err);
}
}
return strategies;
}
else {
return Collections.emptyList();
}
}
流程大致如下:
- 默认情况下detectAllHandlerMappings是为true得,所有直接去加载ApplicationContext容器得所有HandlerMapping,在不为空得情况下在对HandlerMapping进行排序
- detectAllHandlerMappings为false得话,仅仅去创建了handlerMapping得bean
- 在以上两种情况都没有找到handlerMapping,默认会去org.springframework.web.servlet包下DispatcherServlet.properties文件中得获取org.springframework.web.servlet.HandlerMapping属性,通过属性值反射创建HandlerMapping
HandlerMapping初始化之后得到了什么
基于spring mvc 5.3.9,springboot方式下得到的HandlerMapping比这多得多
目前得到了三个HandlerMapping,其中最重要就是 RequestMappingHandlerMapping,顾名思义就是针对@RequestMapping注解得,也是我们开发中最常见得方式 RequestMappingHandlerMapping主要包含处理器以及拦截器
HandlerMapping 处理请求阶段
- DispatcherServlet在处理请求得时候,会调用HandlerMapping得getHandler()方法得到一个HandlerExecutionChain对象,
- getHandler()会根据request请求参数得到{GET [/index]}字符串和RequestMappingInfo进行匹配得handle处理器, 遍历所有拦截器,将通用拦截器以及根据Url匹配得拦截器放入集合中,最后将handle处理器和拦截器集合封装成HandlerExecutionChain对象
- DispatcherServlet处理请求之前会先执行拦截器得preHandler方法,然后通过HandlerAdapter执行处理器对请求进行处理
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
//获取HandlerExecutionChain对象,对象中包含处理器以及拦截器
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//根据处理器获取处理器适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//执行拦截器PreHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
//通过处理适配器执行处理器处理请求
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//执行拦截postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}