springmvc中RequestMapping的解析

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

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,里面包括了处理器,拦截器等

时间: 2024-10-14 11:57:10

springmvc中RequestMapping的解析的相关文章

SpringMVC中 -- @RequestMapping的作用及用法

一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置 <servlet> <servlet-name>servletName</servlet-name> <servlet-class>ServletClass</servlet-class> </servlet> <ser

SpringMVC注解@RequestMapping全面解析---打酱油的日子

1 @RequestMapping("/publication/{publicationType}/{specifyPublisherId}/{specifyPublisherType}/{isPar}") public void queryPublicationList(@PathVariable String publicationType, @PathVariable String specifyPublisherId, @PathVariable String specifyP

SpringMVC中@RequestMapping参数设置

URL路径由value决定,eg:value="/hello". method参数:RequestMethod.POST,RequestMethod.GET请求方法,比如GET.POST 除此之外,还有: param:参数设置 @RequestMapping还支持ANT风格的通配符: @RequestMapping(value="/?/world") 需要类似于http://localhost:8080/SpringHelloWorld/hello/4/world这

SpringMVC中用于绑定请求数据的注解以及配置视图解析器

SpringMVC中用于绑定请求数据的注解 在上一篇文章中我们简单介绍了@RequestMapping与@RequestParam注解,知道了如何去配置地址映射,本篇则介绍一些用于处理request数据的注解. [email protected]注解,该注解用于处理request中的header部分,也就是http请求头的部分,它可以把header部分的值绑定到方法的参数上,示例: package org.zero01.test; import org.springframework.stere

SpringMVC在@RequestMapping配置两个相同路径

这篇博客来自这个问题: 在SpringMVC中@RequestMapping可以配置两个相同的url路径吗. 首先,这个问题会点SpringMVC的人可能都知道答案,但是上次面试中我就回答了可以...可以..Spicy Chicken!!! 参考文章: http://lgbolgger.iteye.com/blog/2105108 这个问题要从 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 讲起了. 首先,在配置文件中声明

SpringMVC中的XXE漏洞测试

SpringMVC框架支持XML到Object的映射,内部是使用两个全局接口Marshaller和Unmarshaller,一种实现是使用Jaxb2Marshaller类进行实现,该类自然实现了两个全局接口,用来对XML和Object进行双向解析.并且XML文件可以是DOM文档.输入输出流或者SAX handler. SpringMVC流行使用注解来快速开发,其中JAXB注解可以对JavaBean中需要与XML进行转化的地方进行标注.比如,实现XML文件到User对象的映射,User对象中使用J

[SpringMVC]SpringMVC学习笔记一: springmvc原理及实例解析.

前言:今天来回顾下SpringMVC的开发原理, 使用图文并茂的方式 来解析其中的内幕, 我相信懂了其中的运行机制后, 对于面试中SpringMVC大家都可以说so easy了. 一, 图示法 第二张图的前端控制器应为DispatcherServlet. 看完图中的整体流程后, 我们再使用实际代码来说明每一步需要处理 的事情. 二. 代码示例 第一步: 用户发送请求, 前端控制器DispatcherServlet开始处理.在web.xml中配置前端控制器: 1 <servlet> 2 <

SpringMVC中@Controller和@RequestMapping用法

一.简介 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示.在SpringMVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注

SpringMVC导入Excule并解析Excule中的数据以及下载Excule模板

把Excule导入,并把Excule中的数据解析出来,包装成对象的属性,保存在数据库中: Excule中的数据: 1.web.xml的配置: <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/java