spring mvc(4) HandlerMapping

  在前面一节里提到,DispatcherServlet在接收到请求后,通过HandlerMapping找到处理请求对应的Controller(其实处理请求器并不一定是Controller,还可以是HttpRequestHandler、Servlet)。下面我们来具体介绍一下spring中提供了那些HandlerMapping以及具体的实现原理。

  BeanNameUrlHandlerMapping,通过url和bean的名称进行匹配并且要求bean的名称以/开头。BeanNameUrlHandlerMapping在启动的时候会读取spring容器中所有以/开头的bean,建立映射关系。 

  例如在xml配置

<bean id="/home.htm" class="controller.IndexController"></bean>

  那么当访问/home.html时,会执行IndexController相应的方法。

  SimpleUrlHandlerMapping,配置url和bean的映射关系进行匹配。相对于BeanNameUrlHandlerMapping他将url和bean名称进行了解藕,但是需要配置以下映射关系,在启动时将映射关系注册到容器中。

<bean id="simpleUrlHandlerMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/index">indexController</prop>
            </props>
        </property>
    </bean>

  spring mvc还提供了拦截器的功能,具体会在下面的章节讲到。所以针对特定的请求,我们还需要获取该请求对应的拦截器。事实上我们通过HandlerMapping接口返回的是一个HandlerExecutionChain。所以HandlerMapping在获取处理器的同时也会获取对应的拦截器(HandlerInterceptor),HandlerExecutionChain内部包含了该url对应的处理器和HandlerInterceptor。

1 public interface HandlerMapping {
2     HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
3 }
View Code

  如果容器中存在多个HandlerMapping,那么会使用哪个HandlerMapping来处理请求呢?在DispatcherServlet进行初始化的时候,它会搜索容器中所有的HandlerMapping,并根据order属性进行排序。当接收到请求后,会循环所有的HandlerMapping,直到有一个HandlerMapping返回HandlerExecutionChain。如果容器中没有定义HandlerMapping怎么办?spring会读取DispatcherServlet.properties配置,默认配置BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping。

DispatcherServlet初始化HandlerMapping:

 1 private void initHandlerMappings(ApplicationContext context) {
 2         this.handlerMappings = null;
 3         //根据orer排序
 4         if (this.detectAllHandlerMappings) {
 5             // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
 6             Map<String, HandlerMapping> matchingBeans =
 7                     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
 8             if (!matchingBeans.isEmpty()) {
 9                 this.handlerMappings = new ArrayList<>(matchingBeans.values());
10                 // We keep HandlerMappings in sorted order.
11                 AnnotationAwareOrderComparator.sort(this.handlerMappings);
12             }
13         }
14         else {
15             //当detectAllHandlerMappings为false时,只使用名为handlerMapping的HandlerMapping
16             try {
17                 HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
18                 this.handlerMappings = Collections.singletonList(hm);
19             }
20             catch (NoSuchBeanDefinitionException ex) {
21                 // Ignore, we'll add a default HandlerMapping later.
22             }
23         }
24 
25         // Ensure we have at least one HandlerMapping, by registering
26         // a default HandlerMapping if no other mappings are found.
27         if (this.handlerMappings == null) {
28             this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
29             if (logger.isDebugEnabled()) {
30                 logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
31             }
32         }
33     }
View Code

猜你喜欢

转载自www.cnblogs.com/zhangwanhua/p/9304562.html