【Spring MVC学习笔记 一】Spring MVC基本概念及理论基础

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【Spring MVC学习笔记 一】Spring MVC基本概念及理论基础

终于学习完了Spring的全部内容,那么接下来的精力就集中在了Spring MVC上边,什么是Spring MVC呢,其实Spring MVC就是通过Java实现MVC的轻量级Web框架,既然是Spring MVC,也就是深度兼容到Spring中的。可以这么理解,其实MVC是一种架构思想,实现方式有很多种,之前我们在Java Web基础系列里【Java Web编程 十四】深入理解MVC架构模式通过JSP+Servlet+JDBC组合实现了MVC架构,抑或是我们古早的Struts框架实现MVC架构,其实就是思想的一种实现方式。那么从今天开始我们就使用Spring MVC来代替JSP+Servlet+JDBC组合实现下MVC架构。

回顾MVC思想

MVC 全名是 Model View Controller,一种软件设计典范,用一种业务数据、逻辑、界面显示分离的方法组织代码,各部分职责如下:

  • 视图
    视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但是已经被一些能显示动态数据的JSP逐步取代了,MVC好处是它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据来源是什么,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式
  • 模型
    模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。不能将模型看出一个只有数据的类,其实模型也包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),现在一般会更加细分:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据业务两部分
  • 控制器
    控制器接受用户的输入并调用模型和视图去完成用户的需求,所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。

在前后端不分离的站点中,JSP充当了视图,Servlet充当了控制器,Model充当了模型。抽象意义上的职责如下图所示:

现在的MVC模型已经演化为如下操作过程,下面的整个项目就是依据这样的分层构建的

MVC各部分的简要职责以及各个模块活动的数据Model如下:

  • View:视图:显示页面 (返回:DTO转VO
  • Controller:控制器:取得表单数据;调用业务逻辑;转向指定的页面(入参:DTO转PO,返回:PO转DTO
  • Model:模型:定义业务数据模型;处理业务逻辑;持久化数据状态

另外基于传递的数据Model,我们可以把其中涉及的数据模型进行划分:PO,持久对象,对应数据库表的对象模型;DTO,传输对象,前端发给后端的请求对象;VO,视图对象,后端返回给前端的对象

回顾JSP+Servlet+JDBC组合实现方式

整体的项目结构如下,前端页面展示使用了JSP,数据持久化使用了JDBC,Controller使用了Servlet,当然因为项目整体比较简单所以就使用了一个Model贯穿始终,实际上应该按照使用层的不同分别定义的:PO,DTO,VO。

可以看到一个MVC框架的工作主要是这几步:

  1. 将url映射到Java类或Java类的方法
  2. 封装用户提交的数据 (DTO)
  3. 处理请求–>调用相关的业务处理(如需持久化数据封装PO)–>封装响应数据(VO)
  4. 将响应的数据进行渲染 . jsp / html 等表示层数据

了解了一个MVC框架的具体工作流程,我们再来看看Spring MVC是如何进行工作的。

Spring MVC基本概念

Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架,目前的版本已经迭代到了官方文档-5.2.0.RELEASE

为什么要使用Spring MVC

我们新来看下为什么使用MVC框架,然后看下历史的框架对比Struts和Spring MVC,最后看下为什么我们更多使用Spring MVC

为什么使用MVC框架

为什么使用MVC框架呢, web容器创造了servlet接口,servlet接口就是开发人员自己实现业务逻辑的地方,servlet接口最大的特点就是根据http协议的特点进行定义:

  • 一方面做servlet开发时候如果使用者对http协议特点不是特别熟悉,都会碰到或多或少令人迷惑的问题,特别是碰到一些复杂特殊的请求时候:例如文件上传,返回特殊的文件格式到浏览器,这时候使用servlet开发就不是很方便了,servlet开发还有个问题可能大家常常被忽视,就是请求的数据的类型转化,http协议传输都是文本形式,到了web容器解析后也是文本类型,如果碰到货币,数字,日期这样的类型需要我们根据实际情况进行转化,如果页面传送的信息非常多,我们就不得不做大量类型转化,这种工作没有什么技术含量,是个体力活而且很容易导致程序错误
  • 另一方面,通用的权限校验、日志记录等通用的内容,每个servlet都需要重复处理一遍,浪费时间

那么为什么MVC框架可以解决这些问题呢?这个就需要聊到一个概念:前端控制器。什么是前端控制器?Front Controller模式 要求在WEB应用系统的前端( Front )设置一个入口控制器( Controller ) ,是用来提供一个集中的请求处理机制,所有的请求都被发往该控制器统统一处理 ,然后把请求分发给各自相应的处理程序。如果没有前端控制器,那么每次请求都只能找到对应的Servlet去处理:

类似代码如下,每个请求都需要精准的找到Servlet的地址进行请求:

package com.example.spring_mvc;
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
@WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {
    private String message;
    public void init() {
        message = "Hello World!";
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        // Hello
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + message + "</h1>");
        out.println("</body></html>");
    }
    public void destroy() {
    }
}

如果有通用的一些代码:如权限检查,授权,日志记录等,每个Servlet都需要重复处理,当然可以使用过滤器去实现,但是实现复杂度还是比较高,所以我们的框架会给我们封装一个前端控制器来解决这个问题:

我们发现这个前端控制器,很像web里面的Filter过滤器:一般的, 我们把处理请求的对象称之为处理器 (Controller)。

  • Apache习惯称之为Action , 如UserAction.
  • Spring习惯称之为 Controller , 如UserController.

从这里能看出使用MVC框架必须在web.xml中配置前端控制器, 一般的要么是要Filter , 要么是Servlet。Struts2基于Filter,SpringMVC基于Servlet

SpringMVC和Struts2对比

SpringMVC和Struts2对比如下,从集成角度和学习成本角度去看,其实Spring MVC更胜一筹

  • Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易实现restful url,而struts2的架构实现起来要费劲,因为Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了
  • 数据共享方面: SpringMVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量,而Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个Action,一个Action对象对应一个request上下文
  • 拦截器实现机制方面,Struts2有以自己的interceptor机制,SpringMVC用AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大
  • Ajax的实现方式方面:SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便
  • 控制器实现方面: Spring MVC的前端控制器是Servlet, 而Struts2是Filter
  • 参数验证方面:SpringMVC验证支持JSR303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感觉太烦乱
  • 请求性能方面Spring MVC会稍微比Struts2 快些,Spring MVC是基于方法设计, 处理器是单例;而Sturts2 是基于类设计,每次发一次请求都会实例一个新的Action对象,Action是多例的。

总之SpringMVC目前的使用率已经远远超过了Struts2, 所以我们现在更多使用Spring MVC做框架的MVC,甚至和Spring结合起来,SpringMVC已经解决零配置了

Spring MVC的优点

Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。DispatcherServlet的作用是将请求分发到不同的处理器,Spring MVC有如下的特点:

  • 轻量级,简单易学
  • 高效 , 基于请求响应的MVC框架
  • 与Spring兼容性好,无缝结合
  • 约定优于配置
  • 功能强大:RESTful、数据验证、格式化、本地化、主题等
  • 简洁灵活

正因为SpringMVC简单 , 便捷 , 易学 , 天生和Spring无缝集成(使用SpringIoC和Aop) , 使用约定优于配置 、能够进行简单的junit测试 、支持Restful风格 、异常处理、本地化、国际化 、 数据验证 、 类型转换等,所以我们更倾向于使用Spring MVC

DispatcherServlet中心控制器

Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 , 围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)。

当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。这样我们的原有的MVC执行方式如下图:

SpringMVC执行原理

简要分析执行流程:DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。我们假设请求的url为 : http://localhost:8080/spring-mvc/hello,如上url拆分成三部分:

http://localhost:8080   服务器域名
spring-mvc              部署在服务器上的web站点
hello                   表示具体的后端控制器

如上url表示为:请求位于服务器localhost:8080上的spring-mvc站点的hello控制器

如上图拆解的整体请求流程如下:其中DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。

  1. 用户发出请求,DispatcherServlet接收请求并拦截请求
  2. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler
  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello
  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
  6. Handler让具体的Controller执行
  7. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView
  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet
  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
  12. 最终视图呈现给用户

所以其实Spring MVC的作用就是一个前置的Servlet的集中管理器

总结一下

最初我们使用简单的JSP和Servlet去处理请求,后来发现业务逻辑越来越复杂,耦合度太高,于是我们发明了MVC思想,并使用JSP+Servlet+JDBC组合实现了最初的MVC架构,随着业务的发展我们觉得MVC架构的每个部分都能被框架化,例如持久层就可以使用MyBatis去优化来取代JDBC,Spring接管和取代所有的业务逻辑Model层,甚至兼容整合其它框架,而前置的简单Servlet请求也可以被框架化为Spring MVC去实现。所以重要的其实是MVC思想,从来不是各种各样的框架,框架的都是为了这种思想落地而产生的实际形式,这是框架存在的意义,搞清楚这点,我觉得才有学习的依据。

相关文章
|
9天前
|
设计模式 前端开发 Java
步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
通过对 `DispatcherServlet`源码的深入剖析,我们了解了SpringMVC请求处理的全流程。`DispatcherServlet`作为前端控制器,负责请求的接收和分发,处理器映射和适配负责将请求分派到具体的处理器方法,视图解析器负责生成和渲染视图。理解这些核心组件及其交互原理,有助于开发者更好地使用和扩展SpringMVC框架。
24 4
|
4月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
27天前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
102 2
|
2月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
2月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
65 2
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
|
2月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
192 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
3月前
|
XML 缓存 前端开发
springMVC02,restful风格,请求转发和重定向
文章介绍了RESTful风格的基本概念和特点,并展示了如何使用SpringMVC实现RESTful风格的请求处理。同时,文章还讨论了SpringMVC中的请求转发和重定向的实现方式,并通过具体代码示例进行了说明。
springMVC02,restful风格,请求转发和重定向
|
4月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
4月前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)