SpringMvc初始化流程源码

SpringMVC解决了哪些问题?
将web页面请求传给服务器
根据不同的请求处理不同的逻辑单元
返回处理结果数据并跳转至响应页面

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
 
  
    <!-- 项目中使用Spring 时,applicationContext.xml配置文件中并没有BeanFactory,要想在业务层中的class 文件中直接引用Spring容器管理的bean可通过以下方式-->
    <!--1、在web.xml配置监听器ContextLoaderListener-->
    <!--ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
    在ContextLoaderListener中关联了ContextLoader这个类,所以整个加载配置过程由ContextLoader来完成。
    它的API说明
    第一段说明ContextLoader可以由 ContextLoaderListener和ContextLoaderServlet生成。
    如果查看ContextLoaderServlet的API,可以看到它也关联了ContextLoader这个类而且它实现了HttpServlet    这个接口
    第二段,ContextLoader创建的是 XmlWebApplicationContext这样一个类,它实现的接口是WebApplicationContext->ConfigurableWebApplicationContext->ApplicationContext->
    BeanFactory这样一来spring中的所有bean都由这个类来创建
     IUploaddatafileManager uploadmanager = (IUploaddatafileManager)
     ContextLoaderListener.getCurrentWebApplicationContext().getBean("uploadManager");-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--2、部署applicationContext的xml文件-->
    <!--如果在web.xml中不写任何参数配置信息,默认的路径是"/WEB-INF/applicationContext.xml,
    在WEB-INF目录下创建的xml文件的名称必须是applicationContext.xml。
    如果是要自定义文件名可以在web.xml里加入contextConfigLocation这个context参数:
    在<param-value> </param-value>里指定相应的xml文件名,如果有多个xml文件,可以写在一起并以“,”号分隔。
    也可以这样applicationContext-*.xml采用通配符,比如这那个目录下有applicationContext-ibatis-base.xml,
    applicationContext-action.xml,applicationContext-ibatis-dao.xml等文件,都会一同被载入。
    在ContextLoaderListener中关联了ContextLoader这个类,所以整个加载配置过程由ContextLoader来完成。-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext.xml</param-value>
    </context-param>
 
 
    <!--使用Spring MVC,配置DispatcherServlet是第一步。DispatcherServlet是一个Servlet,,所以可以配置多个DispatcherServlet-->
    <!--DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller(我们写的Action)来处理。-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name><!--在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。-->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--指明了配置文件的文件名,默认名字为|servlet-name|-servlet.xml,不使用默认配置文件名,而使用dispatcher-servlet.xml配置文件。-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--其中<param-value>**.xml</param-value> 这里可以使用多种写法-->
            <!--1、不写,使用默认值:/WEB-INF/<servlet-name>-servlet.xml-->
            <!--2、<param-value>/WEB-INF/classes/dispatcher-servlet.xml</param-value>-->
            <!--3、<param-value>classpath*:dispatcher-servlet.xml</param-value>-->
            <!--4、多个值用逗号分隔-->
            <param-value>classpath:spring/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup><!--是启动顺序,让这个Servlet随Servletp容器一起启动。-->
    </servlet>
    <servlet-mapping>
        <!--这个Servlet的名字是dispatcher,可以有多个DispatcherServlet,是通过名字来区分的。每一个DispatcherServlet有自己的WebApplicationContext上下文对象。同时保存的ServletContext中和Request对象中.-->
        <!--ApplicationContext是Spring的核心,Context我们通常解释为上下文环境,我想用“容器”来表述它更容易理解一些,ApplicationContext则是“应用的容器”了:P,Spring把Bean放在这个容器中,在需要的时候,用getBean方法取出-->
        <servlet-name>DispatcherServlet</servlet-name>
        <!--Servlet拦截匹配规则可以自已定义,当映射为@RequestMapping("/user/add")时,为例,拦截哪种URL合适?-->
        <!--1、拦截*.do、*.htm, 例如:/user/add.do,这是最传统的方式,最简单也最实用。不会导致静态文件(jpg,js,css)被拦截。-->
        <!--2、拦截/,例如:/user/add,可以实现现在很流行的REST风格。很多互联网类型的应用很喜欢这种风格的URL。弊端:会导致静态文件(jpg,js,css)被拦截后不能正常显示。 -->
        <url-pattern>/</url-pattern> <!--会拦截URL中带“/”的请求。-->
    </servlet-mapping>
</web-app>

对于SpringMVC功能实现分析,首先从web.xml开始,我们先看一下ContextLoaderListener所提供的功能。
一般编程我们可以将Spring配置信息像这样传入Spring容器。
ApplicationConexct ac = new ClassPathXmlApplicationContext("applicationContext.xml");
但在Web下,我们通常是将路径以context-param的方式注册并使用ContextLoaderlistener进行监听读取。
ContextLoaderlistener在启动WEB容器时,自动装配ApplicationContext的配置信息。ContextLoaderlistener实现了ServletContextListener接口,web.xml配置这个监听器,启动容器时,默认执行它实现的方法,使用ServletContextListener接口,可以为客户端请求服务之前像ServletContext添加任意对象。
在这里插入图片描述

每一个web应用都有一个ServletContext与之相关联。ServletContext对象在应用启动时被创建,关闭时被销毁。ServletContext在全局范围内有效,类似于应用中的一个全局变量。
当然我们可以配置自己的ContextListener,放入ServletContext相关数据,运行时候获取。

@WebListener
public class MyDataContextListener implements ServletContextListener {
    private ServletContext context = null;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        this.context = sce.getServletContext();
        context.setAttribute("myData", "this is myData");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        context = null;
    }
}

容器启动后,会调用contextInitialized方法。initWebApplicationContext是用来初始化webApplicationContext。
在这里插入图片描述
WebApplicationContext继承自ApplicationContext,在这个基础上又制定了一些特殊的操作和属性。
在这里插入图片描述
大致步骤:
1.WebApplicationContext是否存在的验证。配置中只允许声明一次ServletContextListener,多次声明影响Spring执行逻辑。然后将创建的WebApplicationContext实例记录在ServletContext中,方便全局调用。
2.调用createWebApplicationContext方法,创建WebApplicationContext实例。
在这里插入图片描述
通过properties中key对应的value就是我们要创建的context类名称。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样就创建了一个XmlWebApplicationContext并加入到了ServletContext中。最后映射当前的类加载器与创建的实例到全局变量currentContextPerThread中。

DispatcherServlet
servlet声明周期是由servlet容器来控制的,分为3个阶段:初始化、运行和销毁。
初始化阶段
servlet容器加载servlet类,把servlet类的class文件中的数据读到内存中。
servlet容器创建一个servletConfig对象,ServletConfig对象包含了servlet的初始化配置信息。
servlet容器创建一个servlet对象。
servlet容器调用serlvet对象的init方法进行初始化。
运行阶段
当servlet容器接收到一个请求时,servlet容器会针对这个请求创建servletRequest和servletResponse对象,然后调用service方法。并把两个参数传递给service方法。service方法通过servletRequest对象获得请求信息。处理该请求。再通过servletResponse对象生成这个请求的相应结果。然后销毁servletRequest和servletResponse对象。
销毁阶段
当web应用被终止时,servlet容器先调用servlet对象的destrory方法,然后再销毁servlet对象,同时也会销毁与servlet对象相关联的ServletConfig对象。我们可以在servlet的destory中可以释放我们所占用的资源。例如关闭数据库连接。
servlet框架由两个Java包组成:java.servlet和javax.servlet.http。java.servlet定义所有servlet类必须实现的接口和类。java.servlet.http采用HTTP通信协议的HttpServlet类。

如果自己实现了一个servlet那么还需要在web.xml中配置一下就好了
在这里插入图片描述

DispatcherServlet初始化
既然是servlet那么初始化是执行的init方法。
在这里插入图片描述
具体步骤:
1.对init-param中配置进行封装。并校验一些属性,防止没有期望的值。
2.将当前servlet实例转化成BeanWapper实例。
3.注册相对于Resource的属性编辑器。当DispatcherServlet属性注入过程遇到Resource类型的属性酒桶使用ResourceEditor去解析。
4.属性注入。注入contextConfigLocation、contextAttribute、namespace等属性。
5.servletBean的初始化。在ContextLoaderListener加载时已经创建了WebApplicationContext实例。这个initServletBean方法用于补充初始化。
在这里插入图片描述
初始化webApplicationContext的方法initWebApplicationContext,该方法工作就是创建或刷新WebApplicationContext实例并对servletr功能所使用的变量进行初始化。
在这里插入图片描述
configureAndRefreshWebApplicationContext方法是用来加载配置文件的。调用的是AbstactApplicationContext提供的refresh方法。

在这里插入图片描述
multipartResolver用于处理文件上传。

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 最大文件大小,单位字节 -->
    <property name="maxUploadSize" value="100000"/> 
</bean>

localeResolver用来对国际化配置的。
1.基于URL参数控制xxx.jd.com?local=zh_CN

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"/>

2.基于session的配置。通过校验用户会话中预置的属性。
3.基于Cookie的配置。通过cookie来获取locale对象。

themeResolver通过主题theme来控制网页风格。一个主题就是一组静态资源如图片或者CSS样式。
需要制定静态资源路径,并且配合相应的解析器。有cookie、session的。

handlerMapping,通过它可以找到摸个路径对应的Controller。
我们可以提供多个HandlerMapping,DispatcherServlet会根据我们优先级排序。如果HandlerMapping能够返回可用的Handler,则不再询问其他的HandlerMapping。
默认情况下,SpringMVC会加载当前系统所有实现了HandlerMappingHandler接口的bean。我们也可以设置detectAllHandlerMappings为false,这样它就只加载名为handlerMapping的bean。

handlerAdapters,典型适配器模式的使用。适配器模式是将一个类的接口是配成用户所期待的。
初始化它也是先检测detect是否为true,为true加载所有的HanderAdapter。如果没找到bean,则尝试加载默认的适配器。
在这里插入图片描述
DispatcherServlet.properties配置文件中指定了默认的adapter。
DispatcherServlet通过处理映射找到Controller后,会轮询处理器适配器HandlerAdapter模块,查找能够处理当前http请求的处理器适配器,处理器适配器模块根据控制器类型,例如简单的处理器类型、注解处理器类型、或远程调用处理器类型,来选择一个适当的处理器适配器的实现,从而适配当前http请求。

SpringMVC 处理器适配器详解

Http请求处理器适配器
仅仅支持对HTTP请求处理器的适配。简单地将HTTP请求对象和响应对象传递给HTTP请求处理器的实现,它并不需要返回值。主要应用在HTTP的远程调用上。
简单控制器处理器适配器
这个实现类将HTTP请求适配到一个控制器的实现进行处理。这里控制器的实现是一个简单的控制器接口的实现。客户端的业务逻辑通常是在控制器接口的实现类中实现的。
注解方法处理器适配器
这个类的实现基于注解实现,需要结合注解方法映射和注解方法处理器协同工作。通过解析声明在注解控制器的请求映射信息来解析相应的处理器方法来处理当前的HTTP请求。在处理过程中,它通过反射来发现处理器方法的参数,调用处理器方法,并映射返回值到模型和控制器对象,最后返回模型和控制器对象给DispatcherServlet。

handlerExceptionResolvers是用于异常处理的,使用这种方式只需要实现resolveException方法,该方法返回一个ModelAndView对象。Spring会搜索所有handlerExceptionResolvers的bean,逐个执行,知道返回ModelAndView。

viewNameTranslator用于当Controller处理器没有返回view或逻辑视图名称,并且方法没有往response输出流里写数据,Spring就会采用约定好的方式提供一个逻辑视图名称。通过getViewName方法来实现的。我们可以实现自己的ToViewNameTranslator接口来约定好没有返回视图名称的时候用什么视图名称。
默认无返回视图解析器通过改造url来得到默认视图的。
在这里插入图片描述
viewResolvers,当Controller将请求处理结果放入到ModelAndView中后,DispatcherServlet会根据ModelAndView选择合适的视图进行渲染。ViewResolver接口定义了resolverViewName方法,根据ViewName创建合适类型的View。

flashMapManager,提供了一个请求存储属性,可供其他请求使用。在使用重定向时非常必要。Flash attributaes在重定向之前缓存以便重定向后还能使用,并立即删除。(这个东西没什么用。单机还能玩一玩)

看完了初始化话,无非就是从sping中取出所有相关类型,排序。要么就是配置detect为false,使用默认名称的bean。如果没有那么就从默认策略中,取出默认的相关bean。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC 是 Spring 框架的一个重要模块,用于开发 Web 应用程序。它采用MVC(Model-View-Controller)设计模式,将应用程序分成三个部分:模型、视图和控制器,以便进行分层开发。 Spring MVC 的源码主要包括以下几个部分: 1. DispatcherServlet DispatcherServlet 是 Spring MVC 的核心控制器,它负责接收用户请求并将请求分发给相应的处理器。它的源码主要包括以下几个方法: - init():初始化 DispatcherServlet。 - doDispatch():分发请求给处理器。 - processRequest():处理 HTTP 请求。 - render():渲染视图。 2. HandlerMapping HandlerMapping 是一个接口,它负责将请求映射到相应的处理器。Spring MVC 提供了多种 HandlerMapping 实现,如 BeanNameUrlHandlerMapping、RequestMappingHandlerMapping 等。它的源码主要包括以下几个方法: - getHandler():根据请求获取处理器。 - registerHandler():注册处理器。 - getHandlerExecutionChain():获取处理器执行链。 3. HandlerAdapter HandlerAdapter 是一个接口,它负责执行处理器。Spring MVC 提供了多种 HandlerAdapter 实现,如 SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter 等。它的源码主要包括以下几个方法: - supports():判断是否支持该处理器。 - handle():执行处理器。 4. ViewResolver ViewResolver 是一个接口,它负责将逻辑视图名映射到实际视图。Spring MVC 提供了多种 ViewResolver 实现,如 InternalResourceViewResolver、JsonViewResolver 等。它的源码主要包括以下几个方法: - resolveViewName():根据逻辑视图名获取实际视图。 - setViewClass():设置视图类。 5. HandlerInterceptor HandlerInterceptor 是一个接口,它负责在处理器执行前后拦截请求。Spring MVC 提供了多种 HandlerInterceptor 实现,如 LocaleChangeInterceptor、ThemeChangeInterceptor 等。它的源码主要包括以下几个方法: - preHandle():处理器执行前拦截请求。 - postHandle():处理器执行后拦截请求。 - afterCompletion():处理器完成后拦截请求。 这些是 Spring MVC 的主要组件,它们共同构成了 Spring MVC 的框架。理解 Spring MVC 的源码不仅需要对 Java Web 开发有深入的了解,还需要对 Spring Framework 有一定的了解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值