springmvc中HandlerMapping是干什么用的

HandlerMapping处理器映射器

作用是根据request找到相应的处理器Handler和Interceptors,然后封装成HandlerExecutionChain对象返回

HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

实现类

HandlerMapping帮助DispatcherServlet进行web请求的url到具体处理类的匹配,用来根据请求的url查找Handler,内部维护的Map<String, Object>映射,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等

 private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();
HanderMapping继承关系
HanderMapping继承关系

spring自带了多个处理器映射实现

  • BeanNameUrlHandlerMapping 根据控制器Bean的名字将控制器映射到URL
  • ControllerBeanNameHandlerMapping 与BeanNameUrlHandlerMapping类似
  • ControllerClassNameHandlerMapping 通过使用控制器的类名作为URL基础将控制器映射到URL
  • DefaultAnnotationHandlerMapping 将请求映射给使用@RequestMapping注解的控制器和控制器方法
  • SimplerUrlHandlerMapping 使用定义在Spring应用上下文的集合将控制器映射到URL
  • RequestMappingHandlerMapping SpringMVC3.1新增的,在springMVC3.1之前,DefaultAnnotationHandlerMapping会在类级别上选中一个控制器,然后通过AnnotationMethodHandlerAdapter定位到具体要调用的方法;而在SpringMVC3.1之后,这些操作全都放生在RequestMappingHandlerMapping中,从类级别和方法级别的@RequestMapping注解中获取到路径映射信息,使得在HandlerInterceptor中获取到的处理器肯定是一个HandlerMethod类型

配置

<!-- 开启注解 -->
<mvc:annotation-driven/>
<bean id="defaultAnnotationHandlerMapping"     class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
mvc:annotation-driven配置的作用
  • <mvc:annotation-driven/>会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdater、ExceptionHandlerExceptionResolver三个bean
  • 支持使用ConversionService实例对表单参数进行类型转换
  • 支持使用@NumberFormatannotation、@DataTimeFormat注解完成数据类型的格式化
  • 支持使用@Vaild注解对JavaBean实例进行JSR 303验证
  • 支持使用@RequestBody和@ResponseBody注解

RequestMappingHandlerMapping源码

由于一般都使用<mvc:annotation-driven/>进行配置,所以就以RequestMappingHandlerMapping为例进行讲解

创建

RequestMappingHandlerMapping实现了ApplicationContextAware接口,会执行setApplicationContext

// 调用链路 org.springframework.context.support.ApplicationObjectSupport#setApplicationContext ——>org.springframework.context.support.ApplicationObjectSupport#initApplicationContext(org.springframework.context.ApplicationContext) -->org.springframework.web.servlet.handler.AbstractHandlerMapping#initApplicationContext
// org.springframework.web.servlet.handler.AbstractHandlerMapping#initApplicationContext
protected void initApplicationContext() throws BeansException {
  // 扩展interceptors的方法,空实现
   extendInterceptors(this.interceptors);
  // 将容器中的所有MappedInterceptor类型的bean添加到mappedInterceptors中
   detectMappedInterceptors(this.adaptedInterceptors);
  // 初始化Interceptor,将interceptors中的对象添加到adaptedInterceptors中
   initInterceptors();
}

RequestMappingHandlerMapping实现了InitializingBean接口,会执行afterPropertiesSet

// org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#afterPropertiesSet
public void afterPropertiesSet() {
   initHandlerMethods();
}
// org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#initHandlerMethods
protected void initHandlerMethods() {
  // 拿到容器中的bean,筛选出Handler
  String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
    BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
    getApplicationContext().getBeanNamesForType(Object.class))
;

  for (String beanName : beanNames) {
   if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
    Class<?> beanType = null;
    try {
     beanType = getApplicationContext().getType(beanName);
    }
    catch (Throwable ex) {
     
    }
        // (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));  判断
    if (beanType != null && isHandler(beanType)) {
          // 将访问地址、Method进行映射
     detectHandlerMethods(beanName);
    }
   }
  }
  handlerMethodsInitialized(getHandlerMethods());
 }
访问

在进行访问的时候会通过org.springframework.web.servlet.DispatcherServlet#getHandler方法来遍历handlerMappings

HandlerExecutionChain handler = hm.getHandler(request);

来调用HandlerMapping的getHandler方法

// org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  // 找到Handler,根据地址找到对应的方法
   Object handler = getHandlerInternal(request);
   if (handler == null) {
      handler = getDefaultHandler();
   }
   if (handler == null) {
      return null;
   }
   // Bean name or resolved handler?
  // 如果找到的handler是一个字符串,可能是beanName,从bean容器中查找
   if (handler instanceof String) {
      String handlerName = (String) handler;
      handler = getApplicationContext().getBean(handlerName);
   }

  // 为handler生成执行链,即为HandlerExecutionChain对象添加interceptor
   HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
  // 跨域处理
   if (CorsUtils.isCorsRequest(request)) {
      CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
      CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
      CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
      executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
   }
   return executionChain;
}
getHandlerInternal
// org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
   String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
   
   this.mappingRegistry.acquireReadLock();
   try {
      HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
      
      return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
   }
   finally {
      this.mappingRegistry.releaseReadLock();
   }
}
getHandlerExecutionChain
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
   HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
         (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

   String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
   for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
      if (interceptor instanceof MappedInterceptor) {
         MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
         if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
            chain.addInterceptor(mappedInterceptor.getInterceptor());
         }
      }
      else {
         chain.addInterceptor(interceptor);
      }
   }
   return chain;
}

https://zhhll.icu/2021/框架/springmvc/底层剖析/2.HandlerMapping/

本文由 mdnice 多平台发布

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾光师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值