SpringMVC框架----->(1) SpringMVC概述和请求处理流程

一、SpringMVC概述和请求处理流程

1、 SpringMVC简介

  • SpringMVC是基于Spring的一个框架,实际上就是Spring的一个模块,专门用来做web开发的。
  • web开发底层是servlet, springmvc中有一个对象是Servlet : DispatherServlet(中央调度器)
    DispatherServlet: 负责接收用户的所有请求, 用户把请求给了DispatherServlet, 之后DispatherServlet把请求转发给我们的Controller对象, 最后是Controller对象处理请求。
  • Spring是容器,ioc能够管理对象,使用< bean >, @Component, @Repository, @Service, @Controller,SpringMVC能够创建对象, 放入到容器中(SpringMVC容器), SpringMVC容器中放的是控制器对象, 我们要做的是使用@Contorller创建控制器对象, 把对象放入到SpringMVC容器中, 把创建的对象作为控制器使用。这个控制器对象能接收用户的请求, 显示处理结果,就当做是一个servlet使用。而使用@Controller注解创建的是一个普通类的对象,不是Servlet。 SpringMVC赋予了控制器对象一些额外的功能。

2、第一个注解的SpringMVC程序

  • 所谓 SpringMVC 的注解式开发是指,在代码中通过对类与方法的注解,便可完成处理器在SpringMVC 容器的注册
(1)在pom.xml文件中加入依赖和插件
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.5.RELEASE</version>
  </dependency>
</dependencies>

<build>
  <plugins>
    <!-- 编码和编译和JDK版本 -->
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>
(2)在web.xml文件中注册中央调度器
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>
A、< load-on-startup/ >

在< servlet/ >中添加< load-on-startup/ >的作用是,标记是否在Web服务器(这里是Tomcat)启动时会创建这个 Servlet 实例,即是否在 Web 服务器启动时调用执行该 Servlet 的 init()方法,而不是在真正访问时才创建。 它的值必须是一个整数。
➢ 当值大于等于 0 时,表示容器在启动时就加载并初始化这个 servlet,数值越小,该 Servlet
的优先级就越高,其被创建的也就越早;
➢ 当值小于 0 或者没有指定时,则表示该 Servlet 在真正被使用时才会去创建。
➢ 当值相同时,容器会自己选择创建顺序。

B、< url-pattern/ >

可以使用两个值:
1、使用扩展名方式,语法:*.xxx,xxx是自定义的扩展名。常用方式 *. html , *.do等等
http://localhost:8080/springmvc/add.html
http://localhost:8080/springmvc/index.html
2、使用斜杆方式,“/”

(3)配置文件位置与名称
  • 中央调度器注册完毕后,可直接在服务器上发布运行。此时,访问浏览器页面,控制台均会抛出 FileNotFoundException 异常。即默认要从项目根下的 WEB-INF 目录下找名称为 Servlet 名称 -servlet.xml 的配置文件。这里的“Servlet 名称”指的是注册中央调度器标签中指定的 Servlet 的 name 值。本例配置文件名springmvc-servlet.xml。
  • 而一般情况下,配置文件是放在类路径下,即 resources 目录下。所以,在注册中央调
    度器时,还需要为中央调度器设置查找 SpringMVC 配置文件路径,及文件名。
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <!--自定义springmvc读取配置文件的位置-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>
(4)创建处理器
  • 在类上与方法上添加相应注解即可。
  • @Controller:表示当前类为处理器
  • @RequestMapping:表示当前方法为处理器方法。该方法要对 value 属性所指定的 URI 进行处理与响应,被注解的方法的方法名可以随意。
@Controller
public class MyController {
    
    
    /**
     * 处理用户提交的请求,springmvc中是使用方法来处理的
     * 方法是自定义的,可以有多种返回值
     */

    /**
     * @RequestMapping:请求映射,作用是把一个请求地址和一个方法绑定在一起
     *                  一个请求指定一个方法处理
     * 属性:
     *  1、value是一个String类型的,表示请求的地址(addUser.html)
     *
     * 说明:使用RequestMapping修饰的方法叫做处理器方法或者控制器方法,
     *          它作用类似Servlet中的doGet(),doPost()方法
     *
     * 返回值:ModelAndView,表示请求的处理结果
     *          Model:请求处理完显示给用户的数据
     *          View:视图,比如jsp等等
     */
    @RequestMapping(value = "/addUser.do")
    public ModelAndView addUser(){
    
    
        //该方法addUser.html的请求,这里不在调用service请求处理了,
        // 直接相当于service调用处理完成了
        ModelAndView mv = new ModelAndView();

        //添加数据
        //框架在请求的最后把数据放入到request作用域中
        //request.setAttribute("zs","张三");
        mv.addObject("zs","张三");
        mv.addObject("lisi","李四");

        //指定视图的完整路径
        //框架对视图执行的转发操作
        //request.getRequestDispather("/jsp/show.jsp").forward(request,response);
        //mv.setViewName("/jsp/show.jsp");
        //mv.setViewName("/WEB-INF/jsp/show.jsp");

        //当配置了视图解析器
        //框架会使用视图解析器的(前缀+文件名+后缀)组成完整路径
        //   /WEB-INF/jsp/+show+.jsp
        mv.setViewName("show");
        //返回视图
        return mv;
    }

    @RequestMapping(value = {
    
    "/remove.html","/remove1.html"})
    public ModelAndView removeUser(){
    
    
        ModelAndView mv = new ModelAndView();
        mv.addObject("zs","删除张三");
        mv.addObject("lisi","删除李四");
        mv.setViewName("show");
        return mv;
    }
}

1、若有多个请求路径均可匹配该处理器方法的执行,则@RequestMapping 的 value 属性中可以写上一个数组。
2、ModelAndView 类中的 addObject()方法用于向其 Model 中添加数据。Model 的底层为一个 HashMap。
3、Model 中的数据存储在 request 作用域中,SringMVC 默认采用转发的方式跳转到视图,本次请求结束,模型中的数据被销毁

(5)创建SpringMVC配置文件
<!--声明组件扫描器-->
<context:component-scan base-package="com.hcz.controller"/>

(6)定义目标页面
  • 在 webapp 目录下新建一个子目录 jsp,在其中新建一个 jsp 页面 show.jsp。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>显示页面</title>
    </head>
    <body>
        <h3>显示用户姓名</h3><br>
        <p>姓名:${zs}</p><br>
        <p>姓名:${lisi}</p>
    </body>
</html>
(7)修改SpringMVC配置文件
  • SpringMVC 框架为了避免对于请求资源路径与扩展名上的冗余,在视图解析器
    InternalResouceViewResolver 中引入了请求的前辍与后辍。而 ModelAndView 中只需给出要跳转页面的文件名即可,对于具体的文件路径与文件扩展名,视图解析器会自动完成拼接。
<!--声明视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--前缀:视图文件路径-->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--后缀:视图文件扩展名-->
    <property name="suffix" value=".jsp"/>
</bean>

3、使用SpringMVC框架web请求处理顺序

  • (1)用户发起addUser.do请求
  • (2)Tomcat服务器通过 web.xml配置文件中的DispatcherServlet的url-pattern将后缀名为 .do的文件交给DispatcherServlet
  • (3)DispatcherServlet根据spring.xml配置文件组件扫描器知道@RequestMapping(value=“addUser.do”)
  • (4)DispatcherServlet把addUser.do转发给MyController的addUser()方法处理
  • (5)框架执行addUser()方法把得到ModelAndView进行处理, 转发到show.jsp
下图是请求的处理顺序图:

在这里插入图片描述

SpringMVC的MVC组件图:

在这里插入图片描述

4、SpringMVC执行流程图

在这里插入图片描述

流程分析:

(1)浏览器发起请求some.do到中央调度器DispatcherServlet

(2)DispatcherServlet接收请求some.so,把请求交给处理器映射器
处理器映射器:springmvc框架中的一种对象,框架把实现了HandlerMapping接口的类都叫做映射器(多个)
处理器映射器的作用:根据请求,从springmvc容器对象中获取处理器对象
MyController controller = ctx.getBean(“some.do”);
框架把找到的处理器对象放入到一个叫做处理器执行链(HandlerExecutionChain)的类中保存
HandlerExecutionChain:类中保存着
1)处理器对象(MyController)
2)项目中的所有的拦截器List< HandlerInterceptor >

(3)DispatcherServlet把(2)中的HandlerExceptionChain中的处理器对象交给了处理器适配器对象(多个)
处理器适配器:springmvc框架中的对象,需要实现HandlerAdapt接口
处理器适配器作用:执行处理器方法(调用MyController.doSome()得到返回值ModelAndView)

(4)DispatcherServlet把(3)中获取的ModelAndView交给视图解析器对象
视图解析器:springmvc框架中的对象,需要交给ViewResoler接口(多个)
视图解析器作用:组成视图完整路径,使用前缀和后缀,并创建view对象
InternalResourceView:视图类,表示jsp文件,视图解析器会创建InternalResourceView对象,这个对象里有一个属性url=/WEB-INF/view/show.jsp

(5)DispatcherServlet把(4)中创建好的View对象获取到,调用View类自己的方法,把Model数据放入到request作用域中,执行对象视图forward,请求结束。

5、SpringMVC执行过程源码分析

(1)创建容器过程
A、通过load-on-start标签指定的1,创建DisaptcherServlet对象
B、DisaptcherServlet它的父类是继承HttpServlet的, 它是一个serlvet, 在被创建时,会执行init()方法。
C、 在init()方法中,创建容器,读取配置文件
 WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
D、把容器对象放入到ServletContext中
getServletContext().setAttribute(key, ctx);
E、创建好容器后,创建@controller注解所在的类的对象, 创建MyController对象,这个对象放入到 springmvc的容器中,容器是map ,类似 map.put(“myController”,MyController对象)
(2)请求处理过程
1)执行servlet的service()
protected void service(HttpServletRequest request, HttpServletResponse response)

       protected void doService(HttpServletRequest request, HttpServletResponse response)


      DispatcherServlet.doDispatch(request, response){
    
    

          调用MyController的.addUser( )方法
      }

doDispatch:springmvc中DispatcherServlet的核心方法, 所有的请求都在这个方法中完成的。

猜你喜欢

转载自blog.csdn.net/hcz666/article/details/113924765