Spring Webmvc启动流程分析

一.Spring MVC介绍

Spring MVC是一种基于Spring实现了Web MVC设计模式的请求驱动类型的轻量级Web框架。MVC我们相信大多数人都已经了解,是将模型与试图进行了解耦,而Spring MVC也与众多的Web框架一样,实现了MVC的设计理念。所以Spring MVC在我的理解下,首先它解决了前端页面和后端代码的分离,其次,它实现了一个URL请求对应一个方法,便于理解与维护,最后,它管理应用所需的生命周期,简化开发。

二.Servlet初始化

Spring Web MVC框架是围绕 DispatcherServlet 设计的,它负责接收HTTP请求而且协调Spring MVC的各个组件完成处理工作。和我们之前用过的Servlet一样,需要在web.xml中配置。他起到的其实就是控制的作用,像我们日常生活中常见的调度中心,也是Spring MVC易于管理且简化代码的核心。
以我作业中的web.xml为例,进行Servlet初始化的分析,下面附上整个web.xml的完全代码。
在web初始化的时候会去加载web.xml文件,会按照配置的内容进行初始化Servlet。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <display-name>Archetype Created Web Application</display-name>

 
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.js</url-pattern>
        <url-pattern>*.html</url-pattern>
        <url-pattern>*.css</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>

            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>
  1. 首先是定义了标签,这个其实就是用于配置了一个全局变量,里面的内容,会被读取,然后加载到整个application中,它是加载web.xml时,第一个被加载的内容。
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
  1. 接着是定义一个listener,它的类是ContextLoaderListener,这是由Spring提供的类,用于在Web容器中创建Ioc容器。它既然是监听器,就负责完成Ioc容器在Web容器中的启动过程,而启动过程其实就是建立上下文的过程,与ServletContext关系密切。
    这里我简单归纳下这个的过程,是通过看类的源码归纳出来的,感兴趣的同学,可以去自己查看ContextLoaderListener的源码。此处就不附上源码了

首先ContextLoaderListener,是实现了 ServletContextListener的接口,继承了 ContextLoader。其中ServletContextListener中有两个方法,这个接口是用于监听Context,Context变化,会出现响应的事件,监听器对于这些事件进行监听并做出相关反应。
在服务器启动时,调用contextInitialized方法,服务器关闭时,调用contextDestroyed方法,这也可以实现Web容器与Ioc容器的生命周期同步。
这里需要提到的是,ContextLoaderListener中具体的初始化Ioc的过程,即contextInitialized方法,是由ContextLoader来完成的,主要就是创建了一个根Ioc容器,既然是根容器,也很好理解,它是唯一的。它会被放入到Context(即application)中,作为全局供整个应用使用。而根容器的创建过程中,正是加载了步骤1中提到的标识中xml文件的内容,在我的代码中,我是加载了dao层,pojo层,service层。

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
public class ContextLoaderListener extends ContextLoader implements ServletContextListener
  1. 其他博文中提到这一步是filter的初始化,我的代码中没有用到过滤器,也就略过了。
  2. 初始化Servlet,这里要注意的是DispatcherServelt其实本质还是我们用过的Servlet,不过这里是通过相应的xml文件进行配置。这里其实还是创建了一个Ioc容器,创建的过程整个与前面是类似的,只不过用的xml配置文件发生了变化,同时,新创建的容器会把原来的根容器当作父容器,这里与前面有所不同的是,这里加入进来并管理的Bean不像前面是全局的,而是局部的,只有这个Servlet使用,这里我是加入并管理的Controller层。需要注意的是这里使用的标签是 ,意思表示是局部的。
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>

三.Ioc容器创建

在第二部分,已经提到了一些关于Ioc容器创建的过程,下面进行归纳总结。
Ioc容器是Spring的核心,负责创建和管理对象,但他在Web容器中没法直接置入,需要有一个启动过程。
(1)在第二部分提到的根Ioc容器是与Web容器有相同的生命周期。而Ioc容器的启动过程离不了的一个概念就是上下文,它的创建其实就是建立上下文的过程。根Ioc容器是用ContextLoaderListener建立的,是具有唯一性的。
首先ContextLoaderListener实现了ServletContextListener接口,其中两个方法分别是用来通过监听Web容器的创建与销毁,来创建Ioc容器与销毁Ioc容器,而Ioc容器的初始化,是通过父类ContextLoader实现的。
在这里插入图片描述

(2)在Spring MVC中涉及到的另一个Ioc容器,就是根据DispatcherServlet创建的子容器,使用web.xml中的init-param中对应的配置文件进行配置。创建的基本方法与父Ioc容器时类似的,这里加入进来的bean时局部的。

四.Bean初始化

  1. Bean概念
    Bean的概念是针对Ioc容器提出来的,其实就是由Ioc容器管理的对象,Ioc容器负责管理它的创建,销毁等。
  2. xml文件配置bean
    下面是在dispacter-servlet中通过xml配置的bean,它对应的类是Spring内置的,是用于解析JSP视图的。
 <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/views/"/><!--设置JSP文件的目录位置-->
        <property name="suffix" value=".jsp"/>
        <property name="exposeContextBeansAsAttributes" value="true"/>
    </bean>
  1. 注解+扫描器配置bean
    这是我们自己写代码过程中主要用的配置方式,用@XXX的形式,简化标签
    下面介绍一下我使用到的注释。
    (1)Service层
    @Service 表示这是业务层对应的bean(处理业务逻辑,比如注入并操作dao)
    @Autowired 等价于@Resource,用于注入bean对象
@Service
public class NeedHomeworkService {
    @Autowired
    private NeedHomeworkDao needHomeworkDao;

(2)Dao层
@Scope 用于控制对象创建,默认是单例模式
@Repository表明这是数据层对应的bean(数据访问层组件)

@Scope("singleton")
@Repository
public class NeedHomeworkDao {
    @Autowired
    private  DatabasePool databasePool;

(3)自定义类
@Component 用于自定义组件,把自定义类实例化到spring容器中,相当于xml文件中的

@Component
public class DatabasePool {

(4)Controller层
@Controller 表明这是控制层对应的bean

@Controller
public class StuOpeController {
    @Autowired

然后在对应的xml文件中开启扫描,在applicationContext中,我加载了dao层,pojo层,service层,在dispatcher-servlet中,我加载了controller层。
基本语法如下

<context:component-scan base-package="dao"/>
    <context:component-scan base-package="pojo"/>
    <context:component-scan base-package="service"/>

五.总结Spring MVC启动过程

此处使用一张网上找的的图进行说明。

(1)解析web.xml中标签下的部署文件,并加载到application中,作为全局共享使用。
(2)ContextLoaderListener创建一个WebApplicationContext类(即Ioc容器),在这一层,是加载一些除了web层以外的其他组件,例如Dao层,Service层等。这个创建的过程,与web容器启动是同步的。并且这个Ioc容器是父容器,是全局共享的。
(3)创建过滤器(如果有需要的话)
(4)初始化web.xml文件中下的xml文件,可以配置多个,在SpringMVC中就是Dispatcher Servlet,这个容器会有自己的上下文以及对应的bean,但是也会获得父容器的上下文,作为自己的父上下文。注意是先获取父类上下文,再创建当前Servlet的子上下文。
注意这里的bean是独属于这个servlet的,是局部的,与前面的全局的bean不同。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值