第一个SpringMVC程序及执行流程详解


一、第一个SpringMVC程序

项目结构
image-20200823002517879


1. 新建一个普通的maven项目,添加web支持

image-20200816220131988 image-20200816220205665

2. pom.xml中添加所需依赖

servlet

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
</dependency>

jsp

<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.2 </version>
</dependency>

SpringMVC相关

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>

3. 编写SpringMVC配置文件

resource目录下新建springmvc-servlet.xml

image-20200823121437232

和Spring的配置文件一样

<?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">

</beans>

添加处理映射器HandlerMapping

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

添加处理器适配器HandlerAdapter

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

添加视图解析器ViewResolver

  • 需要添加所需的前缀后缀,后续会自动拼接名字
<!--视图解析器:DispatcherServlet给他的ModelAndView
	1.获取了ModelAndView的数据
	2.解析ModelAndView的视图名字
	3.拼接视图名字,找到对应的视图 hello
	4.将数据渲染到这个视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
   <!--前缀-->
   <property name="prefix" value="/WEB-INF/jsp/"/>
   <!--后缀-->
   <property name="suffix" value=".jsp"/>
</bean>

4. 在web.xml中配置注册DispatcherServlet

注意

  • DispatcherServlet 需要绑定SpringMVC配置文件,绑定上述创建好的配置文件
  • DispatcherServlet 需要设置启动级别,系统刚启动的时候有些内置的请求可能被处理,这里设置为1,同服务器一同启动
  • 在SpringMVC中,url-pattern常用设置匹配的请求的路径有两种
    • /: 匹配所有的请求(不包括.jsp),一般用/,因为后续会通过视图解析器增加后缀
    • /*: 匹配所有的请求(包括.jsp)
<?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_4_0.xsd"
         version="4.0">

    <!--注册DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--DispatcherServlet要绑定SpringMVC的配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!--启动级别-1-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--/ 匹配所有的请求;(不包括.jsp)-->
   	    <!--/* 匹配所有的请求;(包括.jsp)-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

5. 编写业务类

src/main/java目录下新建controller包,在其中新建HelloController.java

业务实现有两种方式

  1. 实现Controller接口
  2. 增加注解
package controller;

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

public class HelloController implements Controller {

    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws Exception {
        //ModelAndView 模型和视图
        ModelAndView mv = new ModelAndView();
	    //业务代码
        //封装对象,放在ModelAndView中。Model
        mv.addObject("msg","HelloSpringMVC!");
        
        //封装要跳转的视图,放在ModelAndView中
        mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
        return mv;
    }
}

这里实现Controller接口,实现其抽象方法handleRequest,其中分为几个步骤:

  1. 方法需要返回一个ModelAndView,首先创建一个ModelAndView

  2. 向创建好的ModelAndView中存入数据

  3. 封装要跳转的视图,存入ModelAndView中,这里跳转的视图名称为hello,该名称会经过上述的视图解析器ViewResolver增加前缀后缀成完整路径/WEB-INF/jsp/hello.jsp

    image-20200823104829019
  4. 最后返回ModelAndView


6. 在SpringMVC配置文件中注册上述实现类

注意:这里的id为我们要请求的位置,这里请求/hello

处理器映射器会在这个bean里寻找到url的名字(这里就是id)进行处理

<!--Handler-->
<bean id="/hello" class="controller.HelloController"/>

7. 编写要请求的jsp页面

web/WEB-INF下新建jsp包,在其中新建跳转页面hello.jsp

这里显示我们前面在ModelandView存放的数据,以及我们的正常页面;

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${msg}
</body>
</html>

8. 配置Tomcat 启动测试!

我们访问http://localhost:8080/hello
image-20200822125942561


9. 404报错?解决方案

解决办法

打开Project Structure查看项目结构
image-20200822130132859
发现没有lib目录,这时候需要手动添加lib依赖
image-20200822130235168
然后,点击+添加依赖,选中所有依赖
image-20200822130313560
image-20200822130400166

应用,然后重启Tomcat,再次访问http://localhost:8080/hello
image-20200822130459384




二、执行流程分析

image-20200823131819733

图中实线表示SpringMVC框架已经实现的技术,虚线表示需要我们实现


1. DispatcherServlet

前置控制器是整个SpringMVC的核心

用户发出的请求,都会被DispatcherServlet请求拦截

image-20200822232345548

我们上述在浏览器请求的url为http://localhost:8080/hello,该url会被拆成三部分:

  1. http://localhost:8080表示服务器域名

  2. 部署在服务器上的web站点,这里没有设置

    可以在Tomcat中进行配置,如设置为/SpringMVC则web站点为SpringMVC
    image-20200822220013717

  3. hello表示控制器


2. HandlerMapping

处理器映射

  • HandlerMapping根据请求的url查找处理器Handler

HandlerMapping会被DispatcherServlet会自行调用,然后查找Handler

image-20200822232152876
上述我们请求的url被拆解为三部分,然后HandlerMapping通过第三部分hello进行匹配,找到对应的处理器Handler
image-20200823110705019


3. HandlerExecution

具体的处理器Handler

  • 主要作用是根据url查找控制器

上述通过HandlerMapping匹配到了对应的处理器Handler,然后通过HandlerExecution通过url查找到控制器为hello,然后其将解析后的信息传递给DispatcherServlet,如解析控制器映射等

image-20200822232628577


4. HandlerAdapter

处理器适配器

  1. 上述找到了处理器Handler,并返回给了DispatcherServlet

  2. 然后就需要交给HandlerAdapter进行适配并返回

    • HandlerAdapter按照特定的规则(就是实现了Controller接口的类Controller)去执行Handler
      image-20200822233855515

5. Controller

控制器,是具体的类

  • 上述就是实现了Controller接口的类HelloController

接下来的过程分为以下几步

  1. Handler让具体的Controller(HelloController)去执行
  2. Controller将具体的执行信息ModelAndView返回给HandlerAdapter
  3. ``HandlerAdapterModelAndView传递给DispatcherServlet`
    image-20200822233855515

5. ViewResolver

视图解析器

上一步DispatcherServlet获取到了ModelAndView后,就需要通过ViewResolver进行解析
image-20200822234321804

  1. DispatcherServlet调用视图解析器来解析HandlerAdapter传递的逻辑视图名

  2. 然后ViewResolver将逻辑视图名传给DispatcherServlet


6. View

视图

  1. DispatcherServlet根据视图解析器的视图结果,调用具体的视图
  2. 最终视图View呈现给用户

猜你喜欢

转载自blog.csdn.net/qq_45173404/article/details/108181787