zoukankan      html  css  js  c++  java
  • springmvc中RequestMapping的解析

    1

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

    /**
    1.定义一个将请求和处理器进行映射的接口,而这个接口主要的作用就是进行路由,将url映射到HandlerExecutionChain。
    开发人员也可以自己实现这个接口,虽然这是不必须的,因为现在的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(...)是一个模板方法,让子类来返回处理器,处理器就是我们定义的controller,第二部分就是getHandlerExecutionChain方法,这个方法返回的就是 HandlerExecutionChain,这也在前面讲过,就是将某个url映射到其中去,而HandlerExecutionChain其中封装了很多的东西,这其中包括我们调用getHandlerInternal返回的处理器,包括这个针对于这个url的拦截器链。 

    //add time : 17.05.15

        经过了上面两个主要的类之后,到了真正处理处理器逻辑的时候了,这个类就是HandlerAdapter,主要的作用就是针对于处理器进行逻辑操作-> 数据的反序列化,参数的解析,返回数据的反序列化,视图的解析等等。这个接口采用了适配器设计模式,接口主要提供了三个方法:

    public interface HandlerAdapter {
    // 判断此适配器是否支持此处理器 boolean supports(Object handler);
    // 根据请求和处理器处理真正的逻辑,这里面是会调用我们的业务逻辑的 这其中是最为复杂的, ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    // 获取last-modifier 时间
    long getLastModified(HttpServletRequest request, Object handler); }
  • 相关阅读:
    C#中的Dictionary的使用
    关于加密和解密的方法
    单链表逆置
    稀疏矩阵存储
    数组内存地址
    堆和栈的区别
    vc++6.0快捷键
    springMvc-02
    SpringMvc-01
    数据库字段设置问题,具体问题具体分析
  • 原文地址:https://www.cnblogs.com/zr520/p/5987749.html
Copyright © 2011-2022 走看看