框架学习-3.SpringMVC- 1. SpringMVC入门及原理解析

本文详细介绍了SpringMVC的基本概念、优势、工作流程和核心组件,包括DispatcherServlet的作用、MVC模型的组成部分、Servlet的典型应用,以及SpringMVC的配置和注解驱动的实践案例。同时,文章还探讨了SpringMVC的内部执行逻辑,从用户请求到视图渲染的整个过程。最后,通过一个基于注解的入门案例展示了如何简化SpringMVC的配置和控制器编写。
摘要由CSDN通过智能技术生成

1. SpringMVC入门及原理解析 总览

参考狂神说MyBatis课程笔记

参考黑马程序员Spring课程笔记

Spring笔记思维导图:

思维导图笔记链接

问题扩展与汇总:

1. SpringMVC是什么,有什么优势

1.1 三层架构和MVC模型回顾

三层架构
  1. 表现层:WEB层,用来和客户端进行数据交互的。表现层一般会采用MVC的设计模型
  2. 业务层:处理公司具体的业务逻辑的
  3. 持久层:用来操作数据库的

在这里插入图片描述

MVC模型
  • Model数据模型
    • 提供和封装展示的数据,因此包含数据和行为
  • View
    • 指JSP、HTML负责进行模型数据的展示,一般就是我们见到的用户界面,客户想看到的东西
  • Controller
    • 接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。
    • 也就是说控制器做了个调度员的工作。

在这里插入图片描述

回顾Servlet
  • 最典型的MVC就是JSP + servlet + javabean的模式。

  • 编写一个Servlet类,用来处理用户的请求

    • 取得参数

    • 处理业务逻辑

    • 视图跳转

    • package com.kuang.servlet;
      //实现Servlet接口
      public class HelloServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //取得参数
              String method = req.getParameter("method");
              if (method.equals("add")){
                  req.getSession().setAttribute("msg","执行了add方法");
              }
              if (method.equals("delete")){
                  req.getSession().setAttribute("msg","执行了delete方法");
              }
              //业务逻辑
              //视图跳转
              req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
          }
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req,resp);
          }
      }
      
  • 在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_4_0.xsd"
             version="4.0">
        <servlet>
            <servlet-name>HelloServlet</servlet-name>
            <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/user</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • 编写要跳转的jsp页面,对传入的数据进行显示渲染

    • <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>Kuangshen</title>
      </head>
      <body>
          ${msg}
      </body>
      </html>
      
MVC框架要做哪些事情
  1. 将url映射到java类或java类的方法 .
  2. 封装用户提交的数据 .
  3. 处理请求—调用相关的业务处理—封装响应数据 .
  4. 将响应的数据进行渲染 . jsp / html 等表示层数据 .
常见的MVC模型框架:

常见的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF;

常见前端MVC框架:vue、angularjs、react、backbone;

由MVC演化出了另外一些模式如:MVP、MVVM 等等….

1.2 SpringMVC优点

Spring MVC的特点:

  1. 轻量级,简单易学
  2. 高效 , 基于请求响应的MVC框架
    • 可以方便快捷管理多个请求响应
  3. 与Spring兼容性好,无缝结合(使用SpringIoC和Aop)
  4. 约定优于配置
  5. 功能强大:RESTful、数据验证、格式化、本地化、主题等
  6. 简洁灵活,特别是基于注解的开发,非常简洁高效

2. 入门案例(xml配置版)

1)添加坐标依赖

2)配置web.xml,注册DispatcherServlet

  • 注册**SpringMVC封装好的DispatcherServlet,注册好对应的mapping,默认是根目录**
  • 在注册DispatcherServlet中,初始化关联一个springmvc的配置文件
  • 设置启动级别,默认是1
<?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">
    <!--1.注册DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</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:DispatcherServlet-servlet.xml</param-value>
        </init-param>
        <!--启动级别-1-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <!--/ 匹配所有的请求;(不包括.jsp)-->
    <!--/* 匹配所有的请求;(包括.jsp)-->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

3)编写SpringMVC的配置文件

  • 命名规则一般是:注册servlet的名称-servlet.xml
  • 文件放在类路径classpath下,也就是resources路径下
  • 添加固定约束,所有名称是官网上定义好的,直接拿来用
  • 添加 处理映射器
    • 处理DispatcherServlet传入的客户端请求路径
  • 添加 处理器适配器
    • DispatcherServlet通过适配器分发给对应的controller处理
  • 添加 视图解析器
    • DispatcherServlet将ModelAndView传给它
    • 前缀,后缀,会自动拼接上传递的view路径名,跳转到指定的view资源路径
<?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"/>
<!--    视图解析器-->
    <!--视图解析器:DispatcherServlet给他的ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

4)编写我们要操作业务Controller

  • 要么实现Controller接口,要么增加注解;
  • 需要给DispatcherServlet返回一个ModelAndView,装数据,封视图;
// 1.要先导入Controller接口
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 2. 创建封装模型和视图的对象
        ModelAndView modelAndView = new ModelAndView();

        // 3. 封装
        // 3.1 封装对象,model
        modelAndView.addObject("msg", "HelloSpringMVC!");
        // 3.2 封装要跳转的视图,view
        modelAndView.setViewName("test"); //  :/WEB-INF/jsp/hello.jsp
        
        // 4. 将封装结果返回给DispatcherServlet
        return modelAndView;
    }
}

5)将自己的类交给SpringIOC容器,注册bean

<!--Handler,创建bean-->
    <bean id="/hello" class="com.sheng.controller.HelloController"/>

6)写要跳转的jsp动态页面

  • jsp动态页面中,接受DispatcherServlet经视图解析器解析后的ModelAndView数据
  • 处理model中的数据,进行渲染显示
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>springMVC</title>
</head>
<body>
    ${msg}
</body>
</html>
  • 测试结果显示:
在这里插入图片描述
  • 可能会出现的问题:

    可能遇到的问题:访问出现404,排查步骤:

    1. 查看控制台输出,看一下是不是缺少了什么jar包。
    2. 如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!
    3. 重启Tomcat 即可解决!

在这里插入图片描述

3. SpringMVC原理解析;

3.1 中心控制器及总的执行流程

  • Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 ,

  • **围绕DispatcherServlet设计,接受请求,并将请求通过它分派给不同处理器模块处理**,

  • DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)

    img

  • 1.用户与前端控制器(DispatcherServlet)的交互

    • 当==用户发起请求时被前置的控制器(DispatcherServlet)拦截到请求==,
    • 控制器(DispatcherServlet)通过controller、model和view将请求处理、渲染页面,将结果返回给用户
  • 2.DispatcherServlet与Controller的交互

    • DispatcherServlet根据请求参数生成代理请求(mapper),找到请求对应的实际控制器Controller
    • Controller处理请求,创建数据模型model,访问数据库,将model响应给中心控制
  • 3.DispatcherServlet与View的交互

    • DispatcherServlet将封装好的ModelandView,通过视图处理器,找到View,并将model传给view
    • View将model中的数据解析、渲染,并将结果返回给DispatcherServlet
在这里插入图片描述 img

3.2 SpringMVC内部执行逻辑细节

img

假设用户发起的请求的url为 : http://localhost:8080/SpringMVC/hello

​ http://localhost:8080 : 服务器域名

​ SpringMVC: 部署在服务器上的web工程站点

​ hello: 表示控制器

​ 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。

DispatcherServlet与controller的交互细节

  • HandlerMapping为处理器映射
    • DispatcherServlet调用HandlerMapping,
    • HandlerMapping根据请求url查找Handler(IOC管理的bean,用以查找对应的controller)。
  • HandlerExecution表示执行解析映射,其主要作用是根据url查找控制器,
    • 如上url被查找控制器为:hello。
    • HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
  • HandlerAdapter表示处理器适配器
    • DispatcherServlet将解析的映射传给HandlerAdapter。
    • 其按照特定的规则去执行Handler,适配到具体的Controller执行
    • Controller进行处理请求,业务逻辑,创建ModelAndView(其实开发者一般只需要主动做这些),
      • 将具体的执行信息结果封装进modle,返回给HandlerAdapter
    • HandlerAdapter将视图逻辑名("test)"和模型数据ModelAndView传递给DispatcherServlet

DispatcherServlet与View的交互细节

  • ViewResolver视图解析器
    • 来解析DispatcherServlet传递的逻辑视图名。
    • 视图解析器将解析的逻辑视图名返回给DispatcherServlet。
  • 视图View
    • DispatcherServlet根据视图解析器解析的视图结果,找到对应的view文件,并将model传给view
    • view文件进行解析model中的数据、渲染,并将结果返回给DispatcherServlet
    • 最终视图呈现给用户。

4. 基于注解的入门案例

1)添加坐标依赖

2)配置web.xml,注册DispatcherServlet

<?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">
    <!--1.注册DispatcherServlet-->
    <servlet>
        <servlet-name>dispatcherServlet</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:dispatcherServlet-servlet.xml</param-value>
        </init-param>
        <!--启动级别为1 启动顺序,数字越小,启动越早-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--/ 匹配所有的请求;(不包括.jsp)-->
    <!--/* 匹配所有的请求;(包括.jsp)可能会404错误-->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

/ 和 /* 的区别:

  • < url-pattern > / </ url-pattern > 不会匹配到.jsp, 只针对我们编写的请求
    即:.jsp 不会进入spring的 DispatcherServlet类 。
  • < url-pattern > /* </ url-pattern > 会匹配 .jsp,
    会出现返回 jsp视图 时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错

3)编写SpringMVC的配置文件

  • 让IOC的注解生效
    • 配置的形式与Spring容器配置基本类似,
    • 为了支持基于注解的IOC,设置了自动扫描包的功能
  • 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 ……
  • MVC的注解驱动
    • 在spring中一般采用@RequestMapping注解来完成映射关系
    • 要想使@RequestMapping注解生效
      必须向上下文中注册DefaultAnnotationHandlerMapping
      和一个AnnotationMethodHandlerAdapter实例
    • 这两个实例分别在类级别和方法级别处理。
      而annotation-driven配置帮助我们自动完成上述两个实例的注入
  • 配置视图解析器
    • 在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,
    • 这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。
<?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.sheng.controller"/>
    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />

    <!--
    支持mvc注解驱动
        在spring中一般采用@RequestMapping注解来完成映射关系
        要想使@RequestMapping注解生效
        必须向上下文中注册DefaultAnnotationHandlerMapping
        和一个AnnotationMethodHandlerAdapter实例
        这两个实例分别在类级别和方法级别处理。
        而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>

4)编写我们要操作业务Controller

  • @Controller是为了让Spring IOC容器初始化时自动扫描到;
  • @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
  • 方法中声明Model类型的参数是为了把Action中的数据带到视图中;
  • 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。
package com.sheng.controller;

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

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

// 1.要先进行Controller注解,使得当下类被自动注入bean管理
@Controller
@RequestMapping("/HelloController")
public class HelloController{
//    @Override
//    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//        // 2. 创建封装模型和视图的对象
//        ModelAndView modelAndView = new ModelAndView();
//
//        // 3. 封装
//        // 3.1 封装对象,model
//        modelAndView.addObject("msg", "HelloSpringMVC!");
//        // 3.2 封装要跳转的视图,view
//        modelAndView.setViewName("test"); //  :/WEB-INF/jsp/test.jsp
//
//        // 4. 将封装结果返回给DispatcherServlet
//        return modelAndView;
//    }
    //真实访问地址 : 项目名/HelloController/hello
    @RequestMapping("/hello")
    public String testController(Model model) {
        //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
        model.addAttribute("msg", "HelloSpringMVC2!");

        //web-inf/jsp/test.jsp
        return "test";
    }
}

5)写要跳转的jsp动态页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>springMVC</title>
</head>
<body>
    ${msg}
</body>
</html>
  • 测试结果:
在这里插入图片描述
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值