springmvc逻辑分析
2023-01-06 13:30:15 0 举报
springmcv源码
作者其他创作
大纲/内容
spring容器
用于处理上传请求。处理方法是将普通的request包装成MultipartHttpServletRequest,后者可以直接调用getFile方法获取File,如果上传多个文件,还可以调用getFileMap得到FileName->File结构的Map。此组件中一共有三个方法,作用分别是判断是不是上传请求,将request包装成MultipartHttpServletRequest、处理完后清理上传过程中产生的临时资源。
被观察者
HttpRequestHandlerAdapter
三大重要方法
(3)HandlerExceptionResolvers异常拦截器
ModelAndView handle(......) 执行处理器,返回ModelAndView结果
invokeAwareInterfaces
创建springmvc容器并且创建与springmvc的相关对象
ModelAndView handleInternal(....) 执行处理器,返回ModelAndView结果
监听器
军人
传统
警察
BeanNameUrlHandlerMapping处理实现了接口的Controller
观察者模式
无其他实现接口,只走创建bean流程创建bean
不动
http请求
事件源
RequestMappingHandlerAdapter对应handler类型为:@Controller注解
spring
1.因为RequestMappingHandlerAdapter实现了InitializingBean接口,所以要执afterPropertiesSet()方法2.执行的是RequestMappingHandlerAdapter中的afterPropertiesSet方法
多播器
调用onRefresh(wac)方法初始化springMvc九大组件
处理适配器,它的作用用一句话概括就是调用具体的方法对用户发来的请求来进行处理。当handlerMapping获取到执行请求的controller时,DispatcherServlte会根据controller对应的controller类型来调用相应的HandlerAdapter来进行处理。
initApplicationContext(context)
HandlerAdapter目的
初始化HandlerMapping的时候,在DispatcherServlet.properties属性中的匹配了三个实现类,所以在创建HandlerMapping实例的时候分别都要对这三个实现类进行实例化,常用只有两个1.重要方法:getHandler():获得请求对应的处理器和拦截器
(6)LocaleResolver本地语言解析器
HandlerAdapter有三种类型分别对应三种类型Handler
WebApplicationContext 是 ApplicationContext 的扩展。它具有 Web 应用程序所需的一些额外功能。它与普通的 ApplicationContext 在解析主题和决定与哪个 servlet 关联的能力方面有所不同。
执行不同方法的时候,要调用观察者的方法进行处理
springmvc
事件
能
DispatcherServlet
(7)ThemeResolver模板主题处理器
执行
StandardServletMultipartResolver
走创建bean流程
HandlerMapping是一个接口,内部只有一个方法,用来查找Handler的。在SpringMVC中会有很多请求,每个请求都需要一个Handler处理,它的作用是根据request找到对应的Handler。—用来查找Handler的
事件驱动
其它组件都是用来干活的。在干活的过程中难免会出现问题,出问题后怎么办呢?这就需要有一个专门的角色对异常情况进行处理,在SpringMVC中就是HandlerExceptionResolver。具体来说,此组件的作用是根据异常设置ModelAndView,之后再交给render方法进行渲染
springmvc容器
犯罪嫌疑人
afterPropertiesSet()
用于解析主题。SpringMVC中一个主题对应一个properties文件,里面存放着跟当前主题相关的所有资源、如图片、css样式等。SpringMVC的主题也支持国际化,同一个主题不同区域也可以显示不同的风格。SpringMVC中跟主题相关的类有 ThemeResolver、ThemeSource和Theme。主题是通过一系列资源来具体体现的,要得到一个主题的资源,首先要得到资源的名称,这是ThemeResolver的工作。然后通过主题名称找到对应的主题(可以理解为一个配置)文件,这是ThemeSource的工作。最后从主题中获取资源就可以了
使用HandlerMapping根据http请求获取获取对应的Handler
执行ContextLoaderListener监听器的contextInitialized方法
继承
initHandlerMethods()
逻辑执行过程:1、事件源来发布不同的事件2、当发布事件之后会调用多播器的方法来进行事件广播操作,由多播器去触发具体的监听器去执行操作3、监听器接收到具体的事件之后,可以验证匹配是否能处理当前事件,如果可以,直接处理,不过不行,不做任何操作
主动加载
HandlerAdapter处理器适配器实例化
生命周期initservicedestoryservice:doget,dopost
不能
AbstractHandlerMethodAdapter
SimpleControllerHandlerAdapter
循环遍历判断监听器集合,通过事件的不同动作找到合适监听器
方法的作用:1. 设置注解类@ControllerAdvice的类的相关属性2.添加析参数的解析器3.添加@initBinder的注解处理器4.添加返回值处理器
spring的监听器(观察者模式)
实现类
Spring MVC 九大组件
实现Controller接口
web.xml
MultipartResolver实例化
拿着m416追
看到被观察者不同行为的时候触发的反应
1.BeanNameUrlHandlerMapping继承了applicationContextAware接口,所以要执行setApplicationContext方法2.applicationContextAware接口需要ApplicationContextAwareProcess来执行。所以要执行postProcessBeforeInitialization方法3.在postProcessBeforeInitialization中执行setApplicationContext方法4.setApplication()方法ApplicationObjectSupportObject类的
CommonsMultipartResolver
通过调用多播器ApplicationEventMulticaster来发布监听事件
boolean supports(Object handler)判断是否支持该处理器
桥接方法与合成方法
SimpleControllerHandlerAdapter对应handler类型为:实现Controller接口
RequestMappingHandlerAdapter
观察者
initializeBean
发布事件
1.隔离,springmvc容器继承spring的容器,子容器使用父容器的bean对象,父容器不能使用子容器的bean对象。
1.initApplicationContext方法在AbstractDetectingUrlHandlerMapping类中2.方法的作用:在springmvc 容器中,找到所有继承Controller和HttpRequestHandler接口的Controller类的bean对象,并且把相应的映射关系注册到handlerMap集合中
实现HttpRequestHandler接口
Handler有三种类型
拿着手枪追
初始化HandlerMapping的时候,在DispatcherServlet.properties属性中的匹配了四个实现类,所以在创建HandlerMapping实例的时候分别都要对这四个实现类进行实例化,常用只有三个
ViewName是根据ViewName查找View,但有的Handler处理完后并没有设置View也没有设置ViewName,这时就需要从request获取ViewName了,如何从request中获取ViewName就是RequestToViewNameTranslator要做的事情了。RequestToViewNameTranslator在Spring MVC容器里只可以配置一个,所以所有request到ViewName的转换规则都要在一个Translator里面全部实现。
把被观察者遍历观察者通知消息的操作拿出来委托给一个多播器来进行消息通知,或者说通过观察者进行不同的操作
使用ContextRefreshListener执行ContextRefreshedEvent事件,
具体的监听事件ContextRefreshedEvent
两大实现类,没有默认值,注入哪个就用哪个,没有就返回空
1.springmvc是spring框架的一个模块2.springmvc是如何与spring以及tomcat进行整合的
读取springmvc配置文件
web.xml给tomcat使用
setApplicationContext
(9)FlashMapManager缓存数据管理
(5)RequestToViewNameTranslator视图预处理器
使用发布ContextRefreshedEvent事件,用于初始化九大组件
play
1.执行的是AbstractHandlerMethodMapping的initHandlerMethods()方法2.方法的作用:在springmvc 容器中,找到所有标有Controller和RequestMapping注解的bean对象,并且把相应的映射关系注册到相集合中
小结:Handler是用来干活的工具;HandlerMapping用于根据需要干的活找到相应的工具;HandlerAdapter是使用工具干活的人。
原则:先判断,在执行
invokeInitMethods
long getLastModified(......)返回请求的最新更新时间,如果不支持该操作,则返回-1即可
run
web容器tomcat
web容器tomcat启动
1.在创建springmvc之后,通过使用ContextRefreshListener执行ContextRefreshedEvent事件,调onRefresh(wac)在initStrategies(ApplicationContext context)方法中初始化springMvc九大组件2.在初始化springMvc九大组件过程,如果用户有自定义组件那就根据用户的自定义的组件进行初始化跟创建对象,如果没有就使用默认的,但是MultipartResolver组件除外3.MultipartResolver组件,用户有自定义组件那就根据用户的自定义的组件进行初始化跟创建对象,如果没有就为空4.默认组件的存放位置在:在spring-webmvc中模块下的resources文件夹下的DispatcherServlet.properties属性文件中。
sturt1sturt2
观察者,可能存在多个,接受不同的事件来做不同的处理工作
在不同的阶段要处理不同的工作,应该怎么办?观察者模式:监听器,监听事件,多播器(广播器)
初始化Spring MVC 九大组件
(4)ViewResolvers视图解析器
servlet服务端小程序
添加@Controller注解
是否能够处理
springmvc模块初始化流程
三个接口方法:1.isMultipart(request):判断是不是上传请求2.resolveMultipart(request):解析上传请求3.cleanupMultipart(request):清楚临时资源
应该存储一个观察者的集合
1. spring 启动会立即初始化ioc容器 为父容器。2. spring mvc 在发起第一次请求时会初始化 spring mvc容器 为子容器。3. spring 容器初始化的范围是除了controller层的,比如dao层 srever层。4. spring mvc 初始化的范围是controller层。5. 子容器能访问父容器中的对象,父容器访问不到子容器中的对象。6. 在controller层查找容器中的对象会先查找子容器再查找父容器,其他层都是直接从父容器中查找7.父容器和子容器中不能存在相同的bean。
ViewResolver用来将String类型的视图名和Locale解析为View类型的视图。View是用来渲染页面的,也就是将程序返回的参数填入模板里,生成html(也可能是其它类型)文件。这里就有两个关键问题:使用哪个模板?用什么技术(规则)填入参数?这其实是ViewResolver主要要做的工作,ViewResolver需要找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交由不同的视图自己完成
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-config.xml</param-value> </context-param> <servlet> <servlet-name>test</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--SpringMVC配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
创建spring容器并且创建于spring相关的对象
HttpRequestHandlerAdapter对应handler类型为:实现HttpRequestHandler接口
applyBeanPostProcessorsBeforeInitialization
(8)MultipartResolver文件上传解析器
(1)HandlerMapping映射处理器
SpringMVC中的Servlet一共有三个层次,分别是HttpServletBean、FrameworkServlet和 DispatcherServlet。 HttpServletBean直接继承自java的HttpServlet,其作用是将Servlet中配置的参数设置到相应的属性; FrameworkServlet初始化了WebApplicationContext,DispatcherServlet初始化了自身的9个组件。本篇博客的内容就是对9个组件做个概览。 Handler的概念,也就是处理器。它直接应对着MVC中的C也就是Controller层,它的具体表现形式有很多,可以是类,也可以是方法。在Controller层中@RequestMapping标注的所有方法都可以看成是一个Handler,只要可以实际处理请求就可以是Handler。
解析视图需要两个参数:一是视图名,另一个是Locale。视图名是处理器返回的,Locale是从哪里来的?这就是LocaleResolver要做的事情。LocaleResolver用于从request解析出Locale,Locale就是zh-cn之类,表示一个区域,有了这个就可以对不同区域的用户显示不同的结果。SpringMVC主要有两个地方用到了Locale:一是ViewResolver视图解析的时候;二是用到国际化资源或者主题的时候。
对servlet的封装
被观察者具体要执行的动作
谁来调用或者执行发布具体的事件
1.因为RequestMappingHandlerMapping实现了InitializingBean接口,所以要执afterPropertiesSet()方法2.执行的是RequestMappingHandlerMapping中的afterPropertiesSet方法
postProcessBeforeInitialization
RequestMappingHandlerMapping处理Controller和RequestMapping注解
执行监听器执行方法逻辑
添加ContextRefreshListener监听器,用于后续就、执行ContextRefreshedEvent事件
读取web.xml
HandlerMapping实例化
HandlerAdapter接口
读取spring配置文件
选择合适的HandlerAdapter
(2)HandlerAdapters处理器适配器
在执行HandlerAdapter之前,需要获取所有的HandlerAdapter集合,然后遍历HandlerAdapter集合找到合适的HandlerAdapter,在执行
运行
1.什么是桥接方法?(1)桥接方法是jdk1.5之后引入泛型之后,为了使java的泛型方法生成的字节码和1.5版本前的字节码相兼容,由编译器自动生成的方法(2)在使用的时候可以通过Method.isBridge方法来判断一个方法是否是桥接方法,在字节码中桥接方法会被标记为ACC_BRIDGE和ACC_SYNTHETIC ACC_BRIDGE:说明这个方法是由编译生成的桥接方法 ACC_SYNTHETIC:说明这个方法是由编译器生成的,并不会在源代码中出现2. 什么时候编译器会生成桥接方法呢? 一个子类在继承或实现一个父类的泛型方法时,在子类中明确指定了泛型类型,那么在编译时编译器会自动生成桥接方法3.为什么要生成桥接方法呢? 在1.5版本之前创建一个集合对象之后,可以向其中放置任何类型的元素,无法确定和限制具体的类型,而引入泛型之后可以指定存放什么类型的数据, 泛型在此处起到的作用就是检查向集合中添加的对象类型是否匹配泛型类型,如果不正常,那么在编译的时候就会出错,而不必等到运行时才发现错误 但是泛型是在之后的版本中出现的,为了向前兼容,所以会在编译时去掉泛型,但是可以通过反射API来获取泛型的信息,在编译时可以通过泛型来保证 类型的正确性,而不必等到运行时才发现类型不正确,正是由于java泛型的擦除特性,如果不生成桥接方法,那么与1.5之前的字节码就不兼容了。 因为有了继承关系,如果不生成桥接方法,那么SubClass就没有实现接口中声明的方法,语义就不正确了,所以编译器才会生成桥接方法来保证兼容性4.如果在声明的时候直接就指定好了泛型的类型,那么编译的时候就会出现异常情况,这样的话就会把错误提前5.在此方法中只声明了一个方法,但是从字节码中可以看到三个方法,(1) 第一个是无参的构造方法,编译器自动生成(2)第二个是实现接口中的方法(3)第三个是编译器自动生成的桥接方法,可以看到那两个标志,同时方法的参数和返回值都是Object类型
boolean supportsInternal(......)判断是否支持该处理器
MultipartResolver接口
两大方法
Servlet Config和Servlet Context区别?1.ServletConfig: 是Sevlet的配置对象,用来描述Servlet 的基本信息,容器在初始化Servlet 时通过它传递信息给Sevlet2.ServletContext: 指上下文对象,提供了一系列方法Servlet 与Web容器交互3.ServletConfig:局部对象,作用于某个Servle 实例,每个Servlet 都有对应的ServletConfig;4.SevletContext:全局对象 作用于整个Web应用,一个Web应用对应一个ServletContext,多个Servlet实例对应一个 ServletContext。
用来管理FlashMap的,FlashMap主要用在redirect中传递参数
tomcat执行DispatcherServlet父类HttpServletBean的init
收藏
0 条评论
下一页