码迷,mamicode.com
首页 > 移动开发 > 详细

springmvc中RequestMapping的解析

时间:2016-10-22 20:35:07      阅读:290      评论:0      收藏:0      [点我收藏+]

标签:frame   拦截器   pre   不同   key   int   exce   integer   开发人员   

在研究源码的时候,我们应该从最高层来看,所以我们先看这个接口的定义:

package org.springframework.web.servlet;

import javax.servlet.http.HttpServletRequest;

/**
1.定义一个将请求和处理器进行映射的接口。
开发人员也可以自己实现这个接口,虽然这是不必须的,因为现在的springmvc中已经提供了大量的实现,最典型的就是
BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping,RequestMappingHandlerMapping等等,以前的版本中,如果我们没有显示的设置的话
那么就是前面的两个RequestMapping,但是现在的版本是BeanNameUrlHandlerMapping,DefaultAnnotationHandlerMapping这两个,配置了mvc:annotation-driven注解的话 就是
RequestMappingHandlerMapping
)
2.在映射的结果中可以包括0或多个的拦截器,在执行处理器的前面会先执行preHandle,如果拦截器都返回true的时候,才会执行处理器的逻辑
同时处理参数的能力也是非常的强大的,我们可以定义RequestMapping处理各种参数(但是明显不用这样做的,我们可以直接定义参数转化器)

3.因为系统可以设置多个的HandlerMapping,所以我们应该实现Ordered这个接口,表示个各自的优先级,越小优先级越高。默认是Integer.MAX_VALUE.优先级是最低的
*/
public interface HandlerMapping {  //这个属性表示的是url对应的HandlerMapping String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";  //这个request匹配度最高的HanlderMapping String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";   //是否支持类级别的映射 像我们的DefaultAnnotationHandlerMapping就使用了这个属性来表示支持类级别的。(如果我们没有设置的话,默认就是支持的
  //@see AnnotationMethodHandlerAdapter$ServletHandlerMethodResolver.useTypeLevelMapping())
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping"; //也是request中的KEY名称,值时map,存放在的是键值对 String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";  //和上面差不多,但是类别有一些不同 存放的是Matrix Variable(就是值可以用;分割的那个) String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";   //HandlerMapping支持的媒体类型 String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";  /**
  这个这个类的唯一一个方法,根据职责单一原则,我们就明白了,HandlerMapping的唯一职责就是将一个请求根据不同的策略
  最终转化为HandlerExecutionChain这样的一个对象,这里不是一个接口,而是一个类,这个类就是封装了处理器和一系列的
  拦截器,并且代理了这一系列处理的的前置和后置处理
  */
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; }

 通过上面的分析已经大概明白了HandlerMapping的目的,他的目的就是一个请求来了以后,我们需要通过HandlerMapping来构造一个执行后续操作的环境,这里面包括我们定义的支持媒体类型,随请求来的各种参数,系统中设置的拦截器等等。如果要我说,这一步相当于springmvc的入口吧。

我们再看一个基础的抽象类,这个类就是就是提供了一些基本的设施,留下一个主要的工作给子类来进行实现,这是个是AbstractHandlerMapping。因为这个很多的方法,我并不会将类贴出来,主要分析一下这个类实现了哪些的功能,以及我们关注点在哪里,扩展在哪里。
这个抽象类不仅实现了HandlerMapping,而且实现了Ordered接口,这个接口在HandlerMapping中提示了我们就是定义自己的顺序。并且继承了spring的基础设置类,来提供一些ServletContext和WebApplicationContext这些的引用。所以,如果我们要实现自己的HandlerMapping的话,还是建议这个抽象类就OK了。

我们看最主要的一个方法:

    @Override
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        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 = getApplicationContext().getBean(handlerName);
        }
        return getHandlerExecutionChain(handler, request);
    }

其实getHandlerInternal(...)是一个模板方法,让子类来返回处理器,如果是空的话,那么就返回默认的处理器.但是如果我们想要自己设置默认的处理器的话,我们要自己注入。默认是null。如果我们提供了一个string类型的处理器,他会去当前的容器中查找处理器,很奇怪的是,我发现子类中也做了这样的一件事==!,而且这代码还是同一个哥们写的。看来大神的思想我们还是不太懂呢。还有最后的getHandlerExecutionChai非常的重要,拦截器都是在这个方法里面获取到的.  除了这些重要的点,这个抽象类还留了一个子:extendInterceptors(List<Object> interceptors) 留给子类对拦截器做一些操作。

接下来就是对每一种不同类型的HandlerMapping的不同处理了,但是归根结底还是返回HandlerExecutionChain,里面包括了处理器,拦截器等 

springmvc中RequestMapping的解析

标签:frame   拦截器   pre   不同   key   int   exce   integer   开发人员   

原文地址:http://www.cnblogs.com/zr520/p/5987749.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!