SpringMVC 遗漏补充

说到SpringMVC,一般都说Spring将请求与方法进行了映射,所以每次请求都能找到对应的方法,这次我想找到代码层面上是如何处理的,而不是泛泛而谈。我们在springmvc启动的时候说到,由于DispatcherServlet 实现了Servlet,因此会默认实现其init方法,在init方法中找到了我比较感兴趣的两个函数
(1) initHandlerMappings(context)
(2) initHandlerAdapters(context)

这两个函数的内部实现不贴代码了,就是将一些默认的类经常初始化到容器,供请求过来的时候进行调用。ok,这是我前几次看完代码得到的感悟,当时始终没有解决我的一个疑问,到底在什么时候将URL与方法进行了映射?通过Debug跟踪请求也是莫名其妙的Map里面就存在了映射关系,实在没有办法只能反向查找,终于在 AbstractHandlerMethodMapping 这个类中找到了答案。

public abstract class AbstractHandlerMethodMapping<T>
         extends AbstractHandlerMapping implements InitializingBean

AbstractHandlerMethodMapping 是SpringMVC默认的一个Handler,由于其实现了InitializingBean的接口,那么在容器启动的时候就会调用:

@Override
public void afterPropertiesSet() {
    initHandlerMethods();
}

step1:
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class)
扫描引用上下文,获取所有的Bean

step2:
Class<?> beanType = getApplicationContext().getType(beanName);

   protected boolean isHandler(Class<?> beanType) {
    return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
           AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

遍历所有的Bean,筛选拥有注解Controller 或者 RequestMapping的类

step3:
进入最主要的函数体:detectHandlerMethods

protected void detectHandlerMethods(final Object handler) {

    // 获取handler类型
    Class<?> handlerType = (handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());
    final Class<?> userType = ClassUtils.getUserClass(handlerType);

        //  从实体类中获取方法(一般都是controller类)
        //  这边有兴趣的话可以关注一下selectMethods的实现,应该会在工作中会有涉及到
        //  使用反射的方式获所有的方法
    Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
        new MethodIntrospector.MetadataLookup<T>() {
        @Override
        public T inspect(Method method) {
            return getMappingForMethod(method, userType);
        }
    });

        for (Map.Entry<Method, T> entry : methods.entrySet()) {
        Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType);
        T mapping = entry.getValue();
        // 将其映射关系放入到一个对象里面
        registerHandlerMethod(handler, invocableMethod, mapping);
    }
}

大致就是这样的一个过程,感觉像是记录的一个流水账,哈哈

补充:
HandlerMappings在DispatcherServlet的主要作用就是为请求匹配对应的Controller,建议一个映射关系,根据请求查找Handler,Interceptor。HandlerMappings将请求传递到HandlerExecutionChain中,HandlerExecutionChain包含了一个能处理该请求的处理器,已经需要的拦截器。
DispatcherServlet在没有配置处理器的情况下,会默认的从 DispatcherServlet.properties 配置文件中初始化类:BeanNameUrlHandlerMapping/DefaultAnnotationHandlerMapping

 AbstractHandlerMapping是接口HandlerMappings的抽象实现,是所有的HandlerMapping实现类的父类,其作用是初始化拦截器,将拦截器放入到adaptedInterceptors中,在请求过来的时候,调用getHandlerExecutionChain方法,会遍历这个adaptedInterceptors集合,选择匹配的拦截器。
时间: 2024-10-12 23:33:30

SpringMVC 遗漏补充的相关文章

测试中经常会遗漏的几个地方

做测试也有段时间了.在网上随便找了下.发现有些人也有些个类似的东西.就干脆做了点整理,其中对于功能方面的东西见前人大多已经有整理过就直接拖了些进来,还望见谅,当然基本还是属于原创. 希望大家给予补充. 个人认为软件出现的BUG首先第一个责任一般都是测试用例的问题.其次是测试方法(本身的知识).最后则是态度问题.如果测试用例不完善,不论测试人员自身的水平多好,态度多好,都必然会出问题,除非测试人员对测试用例进行了很好的完善.而如果测试用例是完好的,如果自身知识点比较贫乏也是很容易出问题的.例如说测

springmvc mybatis集成配置示例_java

简单之美,springmvc,mybatis就是一个很好的简单集成方案,能够满足一般的项目需求.闲暇时间把项目配置文件共享出来,供大家参看: 1.首先我们来看下依赖的pom: <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.ve

Spring+SpringMVC+Mybatis配置整合

前言 关于SSM框架整合的问题,网络上有很多资源,但是最近想自己配置的时候却发现总是找不到一个完整的配置教程或完整的代码.有一些比较旧的博客里面讲了一些,但是spring的版本还都是3点几.最近自己从网上各个地方找了一些教程,然后试着自己配置了一下,遇到了很多问题,包括报各种各样的异常.现在终于搞好了,记录一下以备不时之需. 正文 话不多说,直接上干货. 在创建好maven的webapp之后,在pom.xml中加入一些配置.完整的文件如下. <project xmlns="http://m

Maven+Mybatis+Spring+SpringMVC实现分页查询(附源码)

版权声明:本文为博主原创文章,转载注明出处http://blog.csdn.net/u013142781 目录(?)[+] 下面小宝鸽将分享一篇Mybatis分页功能的博文,下面将给出详细的步骤,跟着博主的节奏肯定能实现.另外最后还会附上整个工程的源码.如果是没有使用过maven的猿友可自行下载相关的jar包即可. 一.项目搭建 关于项目搭建,小宝鸽以前写过一篇Spirng+SpringMVC+Maven+Mybatis+MySQL项目搭建,这篇文章提供了详细的搭建过程,而且提供了源码下载,接下

springmvc-求助:Springmvc+mybatis+maven开发的web应用,局域IP不可以

问题描述 求助:Springmvc+mybatis+maven开发的web应用,局域IP不可以 5C Springmvc+mybatis+maven开发的web应用,启动后,本机可以访问,外部不可以. 本机有Springmvc+mybatis+maven开发的项目A,以及,struts2+spring+mybatis+maven的项目B.两个项目都是使用配置相同的jetty插件启动,本机访问都正常.问题是:项目A,启动后,局域网的同事通过IP无法访问,经过telnet检查,发现端口不通.但是可以

Mysql学习笔记(十)存储过程与函数 + 知识点补充(having与where的区别)

原文:Mysql学习笔记(十)存储过程与函数 + 知识点补充(having与where的区别) 学习内容:存储程序与函数...这一章学的我是云里雾里的... 1.存储过程...   Mysql存储过程是从mysql 5.0开始增加的一个新功能.存储过程的优点其实有很多,不过我觉得存储过程最重要的优点就是实现了SQL代码的封装,那么我们为什么需要封装SQL语句呢?原因就是当我们在面对一个庞大的数据库的时候,当我们使用外部程序去访问数据库的时候...我们总不能在外部程序中内嵌很多的SQL语句吧...

springmvc整合freemarker怎么弄

问题描述 springmvc整合freemarker整合流程和原理是什么?最好能有个demo! 问题补充:spirngmvc中freemarker自定义标签的使用原理 解决方案 一. 用macro实现自定义指令,例如:自定义指令可以使用macro指令来定义. <#macro greet person> <font size="+2">Hello ${person}!</font> </#macro> macro指令自身不打印任何内容,它只

SpringMVC源码解析- HandlerAdapter - ModelFactory(转)

ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中   我们来看看具体的处理逻辑(直接充当分析目录): 1. 初始化model 1.1 解析类上使用的sessionAttributres,将获取参数合并到mavContainer中 1.2 执行注解了@ModelAttribute的方法,并将结果同步到Model 参数名的生成规则:@ModelAttribute中定义的value > 方法的返回类型决

js文件-springmvc 静态资源 404问题

问题描述 springmvc 静态资源 404问题 项目根目录结构: Web.xml中配置 Spring-sevlet.Xml中配置 首页JSP中调用外部文件 该链接按中Ctrl后再点击,可访问. 之后依旧无法调用JS文件,跪求大神!!!!!!! 解决方案 我也遇到过这个问题.这里有三种方法可以解决:Spring3中js/css/jpg/gif等静态资源无法找到.我习惯第二种 解决方案二: 你的配置文件放到哪里了,有没有正确应用? 解决方案三: 看你的配置,应该是JSP里面引用js文件的路径问题