zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    url参数的获取
    ajax变量作用域的问题
    滚动条自适应宽度的问题
    js发送验证码(倒计时)
    字符串
    值类型和引用类型
    面向对象
    进程
    UI事件
    鼠标跟随
  • 原文地址:https://www.cnblogs.com/zhangwanhua/p/9304562.html
Copyright © 2011-2022 走看看