前言

SpringMVC是Spring框架提供的构建 Web 应用程序的mvc模块
是一个很优秀的Web框架

这篇将解析SpringMVC的执行流程


DispatcherServlet

从前面:SpringMVC - 从Servlet到SpringMVC中可以看到:

在最初的Servlet的web阶段:
在这里插入图片描述

一切都是在Web服务器中web.xml中自己手动配置一个个Servlet

而在SpringMVC中,通过增加一“层”DispatcherServlet:

在这里插入图片描述

使得在Web.xml中,只需要注册DispatcherServlet,就可以不用管Web.xml了

web.xml中配置DispatcherServlet:

    <!--注册DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet
        </servlet-class> 
        
        <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param> 
    </servlet>
   
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

DispatcherServlet负责了繁琐的注册、转发功能


SpringMVC执行流程

完整的SpringMVC执行流程:
在这里插入图片描述

其中DispatcherServlet就是注册转发,其中关联了springmvc配置文件,
配置文件配置了处理器映射器、处理器适配器、视图解析器

SpringMVC - 从Servlet到SpringMVC第二个阶段:从类的角度看SpringMVC

springmvc-servlet.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--处理器映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

    <!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter "/>

    <!--视图解析器 : 模板引擎thymeleaf-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--BeanNameUrlHandlerMapping:bean-->
    <bean id="/hello" class="com.learn.controller.HelloController"/>
</beans>

Controller类:

package com.learn.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

        ModelAndView mv = new ModelAndView();

        //业务代码
        String result = "HelloSpringMVC";

        mv.addObject("msg",result);

        //视图跳转
        mv.setViewName("test");

        return mv;
    }
}

这里配置了:

  • 处理器映射器:BeanNameUrlHandlerMappi, 根据url请求去匹配bean的name属性url,从而获取Controller

对应着<bean id="/hello" class="com.learn.controller. HelloController"/>
意思是:解析URL请求,如果是/hello,就转发到HelloController

  • 处理器适配器:SimpleControllerHandlerAdap,调用controller里面方法,返回modelAndView

执行Controller中的handleRequest方法(HelloController实现Controller接口),返回ModelAndView, HandlerAdapter将ModelAndView返回给DispatcherServlet。

  • 视图解析器:InternalResourceViewResolver,根据配置的属性解析后端返回的值

DispatcherServlet请求ViewReslover去进行视图解析,也就是把setViewName得到的跳转页面mv.setViewName("test")拼接前缀后缀(/WEB-INF/jsp/test.jsp)得到完整的url,解析该界面

ViewReslover向DispatcherServlet返回View

DispatcherServlet进行视图渲染,将模型数据(在ModelAndView对象中)填充到request域,完成jsp页面

最终,DispatcherServlet将View响应给用户

实际开发,并不会通过继承类实现SpringMVC,而是通过注解


注解实现SpringMVC

springmvc-servlet.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">


    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.learn.controller"/>

    <!-- 支持mvc注解驱动
    在spring中一般采用@RequestMapping注解来完成映射关系 要
    想使@RequestMapping注解生效 必须向上下文中注册RequestMappingHandlerMapping和RequestMappingHandlerAdapter实例
    这两个实例分别在类级别和方法级别处理。
    而annotation-driven配置帮助我们自动完成上述两个实例的注入。 -->
    <mvc:annotation-driven/>
 

	<!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver "
          id="internalResourceViewResolver"> <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

Controller:

package com.learn.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(Model model){

        //封装数据
        model.addAttribute("msg","Hello SpringMVC Annotation");

        return "hello";//被视图解析器处理
    }

}

这里并没有显示的配置处理器映射器、处理器适配器,而是<mvc:annotation-driven/>自动配置默认映射器、适配器

  • RequestMappingHandlerMapping:会把Controller里面带有@RequestMapping注解的方法都加到一个容器里面
  • RequestMappingHandlerAdapter:根据自定义配置可以对经过这些方法的请求的数据或者返回的数据做一些额外的处理

视图解析器ViewResolver

在前面配置文件,我们配置了视图解析器:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver " id="internalResourceViewResolver">
   <!-- 前缀 -->
   <property name="prefix" value="/WEB-INF/jsp/"/>
   <!-- 后缀 -->
   <property name="suffix" value=".jsp"/>
</bean>

在Controller类,返回ModelAndView(Model),对象中主要封装了两个属性:view和model。其中view可以是字符串类型也可以是View类型,如果是字符串类型,则表示逻辑视图名,如果是View类型,则其即为我们要转换的目标view

如果返回值是ModelAndView,需要页面跳转就需要设置mv.setViewName("test");
设置逻辑视图名(或者new一个View对象)

如果使用Model,即只保存Model模型数据,就需要return "hello",表示跳转到逻辑视图

视图的解析可以分为两个步骤:①解析逻辑视图名;②渲染视图,Spring抽象了两个接口:ViewResolver和View

ViewResolver接口:通过用户提供的逻辑视图名根据一定的策略生成一个View对象

分析实现类,解析:

  • 实例化View对象
  • 设置目标视图地址
  • 初始化视图的一些基本属性,如需要暴露的bean对象
  • 调用View对象的初始化方法对其进行初始化

在这里插入图片描述

View接口:根据视图信息和需要填充的模型数据进行视图的渲染

分析实现类,渲染分为两步:

  • 将需要在页面渲染使用的model数据设置到request中;
  • 按照当前请求的方式(include或forward)来将当前请求转发到目标文件中,从而达到目标文件的渲染

在这里插入图片描述


总结

SpringMVC的执行流程主要是分析:DispatcherServlet、HandlerMapping、HandlerAdapter、ViewResolver四个对象

执行流程为:

  • 用户HTTP请求
  • DispatcherServlet调用处理器映射器HandlerMapping,HandlerMapping根据URL请求找到对应的Controller,生成相应的对象返回给DispatcherServlet
  • DispatchServlet得到处理器Controller,调用处理器适配器HandlerAdapter,会执行Controller中的handleRequest方法(RequestMappingHandlerAdapter即执行存在RequestMapping注解的方法),返回ModelAndView给DispatcherServlet
  • DispatcherServlet调用相应的视图解析器ViewResolver,ViewResolver先解析逻辑视图,找到对应的jsp等页面,然后使用Model模型数据渲染视图(填充数据),返回最终的View给DispatcherServlet
  • DispatcherServlet返回View给用户

这就是SpringMVC基本的执行流程,并没有涉及到源码的内容

学海无涯苦作舟

都看到这了,点个赞呗(^_−)☆

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐