Spring学习 基础(三)MVC

5、Spring MVC

传统Web模式:

  1. Model:系统涉及的数据,也就是 dao 和 bean。
  2. View:展示模型中的数据,只是用来展示。
  3. Controller:处理用户请求都发送给 ,返回数据给 JSP 并展示给用户。

img

随着 Spring 轻量级开发框架的流行,Spring 生态圈出现了 Spring MVC 框架, Spring MVC 是当前最优秀的 MVC 框架。相比于 Struts2 , Spring MVC 使用更加简单和方便,开发效率更高,并且 Spring MVC 运行速度更快。

Spring MVC 下我们一般把后端项目分为 Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。

组件:
  • DispatcherServlet核心的中央处理器,负责接收请求、分发,并给予客户端响应。
  • HandlerMapping处理器映射器,根据 uri 去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler 一起封装。
  • HandlerAdapter处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler;
  • Handler请求处理器,处理实际请求的处理器。
  • ViewResolver视图解析器,根据 Handler 返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给 DispatcherServlet 响应客户端
流程:
  1. 客户端(浏览器)发送请求, DispatcherServlet拦截请求。
  2. DispatcherServlet 根据请求信息调用 HandlerMapping 。HandlerMapping 根据 uri 去匹配查找能处理的 Handler(也就是我们平常说的 Controller 控制器) ,并会将请求涉及到的拦截器和 Handler 一起封装。
  3. DispatcherServlet 调用 HandlerAdapter适配执行 Handler 。
  4. Handler 完成对用户请求的处理后,会返回一个 ModelAndView 对象给DispatcherServlet,ModelAndView 顾名思义,包含了数据模型以及相应的视图的信息。Model 是返回的数据对象,View 是个逻辑上的 View。
  5. ViewResolver 会根据逻辑 View 查找实际的 View。
  6. DispaterServlet 把返回的 Model 传给 View(视图渲染)。
  7. 把 View 返回给请求者(浏览器)

原理.png

层次结构
  1. Model 层(Model)
  • 数据访问对象(Data Access Object, DAO):与数据库的交互,负责提供数据操作的方法。
  • 服务层(Service Layer):封装业务逻辑,进行事务管理。
  • 数据传输对象(Data Transfer Object, DTO):在各层之间传输数据。
  1. 视图层(View)
  • 视图技术:如 JSP、FreeMarker、Thymeleaf 等,用来渲染界面。
  • 静态资源:如 HTML、CSS、JavaScript 文件。
  1. 控制层(Controller)
  • DispatcherServlet: 作为前端控制器,所有的请求都会先经过它。它负责将请求路由到相应的处理器,并处理其他如多视图解析、国际化、主题解析等。
  • 控制器(Controllers):处理用户请求,将请求映射到对应的处理逻辑,并返回响应或视图名给前端。
  • 表单对象(Form Object)/命令对象(Command Object):封装客户端提交数据。

除了这三个主要层次外,在实际的Spring MVC应用中,还可能有以下组件或层次:

  1. Web 层
  • 过滤器(Filters):进行请求的预处理和响应的后处理。
  • 拦截器(Interceptors):在控制器执行前后或视图渲染前执行特定逻辑。
  1. 配置层
  • 配置类或XML文件:定义 Spring Bean、数据源、事务管理器等配置信息。
  1. 安全层
  • Spring Security:提供认证和授权的机制来保护应用程序。

DTO和DAO?

  • DTO 主要用于传输跨层或跨系统边界的数据。

  • DAO 专注于提供数据访问技术的抽象,例如数据库操作。

    目的:DTO 主要用于封装从一个系统到另一个系统的数据传输,是一种简单的Java对象,它用于聚合多个数据项以便于传输。
    作用范围:DTO 通常用于服务层与控制层之间或者不同应用程序/服务之间的数据传递。DTO 的目的是减少数据交换时的网络开销,并且可以定制所需展现给客户端的数据结构。
    内容:DTO 不包含任何业务逻辑,仅包含数据字段及其getter和setter方法。有时候,DTO 也可能包含一些简单的转换逻辑或校验逻辑。
    示例:如果需要展示用户信息和他们的订单数量,可以创建一个 UserOrdersDTO 类来封装这两类信息,即使用户信息和订单数量来自不同的源头。目的:DAO 是指访问数据源的对象,它封装了对数据源CRUD(创建、检索、更新、删除)操作的实现。
    作用范围:DAO 直接与数据存储(如数据库)打交道。它抽象和封装了所有与数据持久化相关的操作,使上层业务逻辑不直接依赖于底层的数据持久化细节。
    内容:DAO 通常会提供各种方法来访问数据源,如 findById, findAll, save, update, 和 delete 等。
    示例:有一个 UserDAO 类,提供了获取用户信息、保存新用户等与用户表直接关联的数据库操作方法。
    

DispatcherServlet?

  • 请求路由DispatcherServlet 根据请求的URL来确定选择哪个控制器(Controller)进行处理,并且将请求转发给相对应的控制器。
  • 控制器选择:通过使用处理器映射(Handler Mapping)来识别URL请求所对应的控制器。
  • 调用适配器:使用处理器适配器(Handler Adapter)来执行控制器中相应的方法。
  • 模型和视图解析:控制器处理完请求后,返回一个模型和视图(ModelAndView)对象,DispatcherServlet 会根据这个对象来选择相应的视图技术进行渲染。
软件架构

在软件架构中,持久层(Persistence Layer)、业务层(Business Layer)和表示层/视图层(Presentation Layer)是三个主要的层次结构,它们各自负责不同的功能区域,并且通常相互分离,以实现关注点分离(Separation of Concerns)。以下是每一层的简单介绍:

持久层(Persistence Layer)

持久层,也称为数据访问层(Data Access Layer),负责与数据库进行交互,执行CRUD操作(创建、读取、更新、删除)。它提供了一个抽象层使得业务逻辑可以访问数据库操作所需的数据。在Java应用中,这一层可以通过使用ORM框架如Hibernate,或者使用数据访问技术如JDBC、JPA、MyBatis来实现。

业务层(Business Layer)

业务层包含应用程序的业务逻辑,其核心功能是实现应用程序的业务规则。业务层协调应用程序的工作流程,处理用户请求,并对持久层发送的数据执行业务决策。在复杂应用中,业务层可能还会处理事务、授权和其他核心功能。常见的Spring注解@Service就是用来标记业务层的组件。

表示层/视图层(Presentation Layer)

表示层是用户看到并与之交互的界面,它负责数据的展示和用户输入的处理。在Web应用中,表示层可以由HTML、CSS和JavaScript组成,而在服务器端,Spring MVC框架中的@Controller注解被用来处理HTTP请求,并返回对应的视图名称或响应体。表示层通常从业务层获取数据,并将用户输入传送到业务层进行处理。

每层都专注于其职责范围内的特定任务,从而实现了代码的模块化和清晰的架构设计。通过这种分层,开发人员能够独立地开发和测试每个层次,提高了应用程序的维护性和可扩展性。在Spring框架中,这些层通常由不同的Spring组件来实现,比如使用@Repository注解的类实现持久层,@Service注解的类实现业务层,@Controller或@RestController注解的类实现表示层。

常用Bean

特殊bean.png

<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 --> ResourceViewResolver
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/" /><property name="suffix" value=".jsp" />
</bean>
<!-- 上传限制 --> MultipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 上传文件大小限制为31M,31*1024*1024 --><property name="maxUploadSize" value="32505856"/>
</bean>//当解析器MultipartResolver完成处理时,请求便会像其他请求一样被正常流程处理。@RequestMapping(path = "/form", method = RequestMethod.POST)public String handleFormUpload(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) {if (!file.isEmpty()) {byte[] bytes = file.getBytes();// store the bytes somewherereturn "redirect:uploadSuccess";}return "redirect:uploadFailure";
}
统一异常处理怎么做?

使用注解的方式统一异常处理,具体会使用到 @ControllerAdvice + @ExceptionHandler 这两个注解 。这种异常处理方式下,会给所有或者指定的 Controller 织入异常处理的逻辑(AOP),当 Controller 中的方法抛出异常的时候,由被@ExceptionHandler 注解修饰的方法进行处理。

异常处理方式.png

@ExceptionHandler(Exception.class)
public Object exceptionHandler(Exception ex, HttpServletResponse response, HttpServletRequest request) throws IOException {String url = "";String msg = ex.getMessage();Object resultModel = null;try {if (ex.getClass() == HttpRequestMethodNotSupportedException.class) {url = "admin/common/500";System.out.println("--------毛有找到对应方法---------");} else if (ex.getClass() == ParameterException.class) {//自定义的异常} else if (ex.getClass() == UnauthorizedException.class) {url = "admin/common/unauth";System.out.println("--------毛有权限---------");}String header = req.getHeader("X-Requested-With");boolean isAjax = "XMLHttpRequest".equalsIgnoreCase(header);String method = req.getMethod();boolean isPost = "POST".equalsIgnoreCase(method);if (isAjax || isPost) {return Message.error(msg);} else {ModelAndView view = new ModelAndView(url);view.addObject("error", msg);view.addObject("class", ex.getClass());view.addObject("method", request.getRequestURI());return view;}} catch (Exception exception) {logger.error(exception.getMessage(), exception);return resultModel;} finally {logger.error(msg, ex);ex.printStackTrace();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/733353.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C if 语句

一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。 语法 C 语言中 if 语句的语法&#xff1a; if(boolean_expression) {/* 如果布尔表达式为真将执行的语句 */ }如果布尔表达式为 true&#xff0c;则 if 语句内的代码块将被执行。如果布尔表达式为 false&#xff0c;…

poll开发服务器

int poll(struct pollfd *fds, nfds_t nfds, int timeout); 函数说明&#xff1a;与select类似&#xff0c;委托内核监控可读&#xff0c;可写&#xff0c;异常事件。 函数说明&#xff1a; fds&#xff1a;一个struct pollfd结构体数组的首地址 struct pollfd { …

天猫淘宝详情接口API揭秘:实现个性化商品推荐!

天猫淘宝作为中国最大的电商平台&#xff0c;拥有庞大的商品库存和众多用户&#xff0c;为了提高用户购物体验并满足其个性化需求&#xff0c;天猫淘宝推出了详情接口API&#xff0c;通过智能算法实现个性化商品推荐。联讯数据将为您揭秘详情接口API的实现原理和功能。 个性化商…

信息抽取在旅游行业的应用:以景点信息抽取为例

开源项目推荐 今天先给大家推荐一个开源项目&#xff0c;多模态AI能力引擎平台: 免费的自然语言处理、情感分析、实体识别、图像识别与分类、OCR识别、语音识别接口&#xff0c;功能强大&#xff0c;欢迎体验。 https://gitee.com/stonedtx/free-nlp-api 场景描述 在旅游行业…

【新书推荐】17.3 字符串操作举例

本节内容&#xff1a;字符串操作举例。 ■例3&#xff1a;接收字符串去掉空格后逆向输出&#xff0c;t17-3.asm。 ■例4&#xff1a;字符串拼接&#xff0c;t17-4.asm。 ■例5&#xff1a;判断子串&#xff0c;t17-5.asm。 17.3.1 例3&#xff1a;接收字符串去掉空格后逆向输出…

如何关闭 Visual Studio 双击高亮

[问题描述]&#xff1a; 最近 Visual Studio 更新后&#xff0c;双击选中关键字快要亮瞎我的眼睛了 &#x1f440;&#x1f440; [解决方法]&#xff1a; 摸索了一下&#xff0c;找到了关闭的方法&#xff1a;工具 → 选项 → 文本编辑器 → 常规&#xff0c;然后取消 勾选 sel…

蓝桥杯-串的处理,幸运数字

参照大佬写法: #include<iostream> #include<cstring> using namespace std; int main(){string str;getline(cin,str);//可以将带有空格的string输入for(int i0;i<str.size();i){if(i0&&str[i]>a&&str[i]<z) str[i]-32;//单词首字母小…

如何使用LEAKEY轻松检测和验证目标服务泄露的敏感凭证

关于LEAKEY LEAKEY是一款功能强大的Bash脚本&#xff0c;该脚本能够检测和验证目标服务中意外泄露的敏感凭证&#xff0c;以帮助广大研究人员检测目标服务的数据安全状况。值得一提的是&#xff0c;LEAKEY支持高度自定义开发&#xff0c;能够轻松添加要检测的新服务。 LEAKEY主…

【unity小技巧】Unity人物衣服布料系统的探究 —— Cloth组件

文章目录 一、Cloth组件解释基本介绍出于性能的考虑, 可以对Cloth产生影响的Collider只有两种打开编辑模式绘制 二、基本使用1. 创建出一个空物体2. 在空物体上添加cloth组件&#xff0c;可以直接点击Add Component搜索cloth添加&#xff0c;也可以在工具栏 Component–>phy…

Android UI自动化测试框架—SoloPi简介

1、UI自动化测试简介 软件测试简介 ​软件测试是伴随着软件开发一同诞生的&#xff0c;随着软件规模大型化&#xff0c;结构复杂化&#xff0c;软件测试也从最初的简单“调试”&#xff0c;发展到当今的自动化测试。 ​ 自动化测试是什么呢&#xff1f;自动化测试是把以人为…

图分割 Graph Partition 学习笔记1

文章目录 前言一、graph-partition是什么&#xff1f;二、具体分类三、graph-partition的意义参考链接 前言 最近在学习图论划分的方法&#xff0c;碰巧搜索到了这个算是对我而言全新的一个体系&#xff0c;在这里将逐步记载自己的学习资料和进度&#xff0c;希望和大家一起探讨…

HAProxy集群与常见的Web集群软件调度器对比

一.常见的Web集群调度器 Web集群调度器分为软件和硬件&#xff1a; 1.常用软件调度器&#xff1a; &#xff08;1&#xff09;LVS&#xff1a;性能最好&#xff0c;搭建复杂 &#xff08;2&#xff09;Nginx&#xff1a;性能较好&#xff0c;但集群节点健康检查功能呢不强&…

Rust教程:How to Rust-从开始之前到Hello World

本文为第0篇 专栏简介 本专栏是优质Rust技术专栏&#xff0c;推荐精通一门技术栈的蟹友&#xff0c;不建议基础的同学&#xff08;无基础学Rust也是牛人[手动捂脸]&#xff09; 感谢Rust圣经开源社区的同学&#xff0c;为后来者提供了非常优秀的Rust学习资源 本文使用&…

为什么不用 index 做 key?

“在 Vue 中&#xff0c;我们在使用 v-for 渲染列表的时候&#xff0c;为什么要绑定一个 key&#xff1f;能不能用 index 做 key&#xff1f;” 在聊这个问题之前我们还得需要知道 Vue 是如何操作 DOM 结构的。 虚拟DOM 我们知道&#xff0c;Vue 不可以直接操作 DOM 结构&am…

避免重复数据产生

在MySQL表中&#xff0c;可以通过创建唯一索引或唯一约束来确保表中除了ID以外的其他字段不能有两条记录相同的值。 创建唯一索引&#xff1a; CREATE UNIQUE INDEX index_name ON table_name (column1, column2, ...); 其中&#xff0c;index_name是索引的名称&#xff0c;ta…

AI大模型,掀起新一波智能浪潮!

AI大模型的出现&#xff0c;标志着人工智能技术迈入了一个新的阶段。这些巨大的模型不仅在规模上超越了以往任何其他人工智能系统&#xff0c;而且在性能上也取得了巨大的突破。由于其庞大的参数量和复杂的结构&#xff0c;AI大模型在各个领域展现出了强大的学习能力和推理能力…

【机器学习】在Python中进行K-Means聚类和层次聚类

Python中聚类算法API的使用指南 聚类分析是数据分析中一种常见的无监督学习方法&#xff0c;通过将相似的对象分组在一起&#xff0c;我们能够识别出数据集中的自然分群。本文将介绍如何使用Python中的聚类算法接口&#xff0c;KMeans和层次聚类方法。 K-Means 聚类 K-Means…

EdgeX Foundry - 连接 Modbus 设备

文章目录 一、概述1.安装说明2.Modbus Slave 工具 二、连接 Modbus 设备1.docker-comepse2.设备配置文件3.启动 EdgeX Foundry4.访问 UI4.1. consul4.2. EdgeX Console 5.创建 Modbus 设备5.1.创建设备配置文件5.2.添加设备 6.测试6.1.命令6.2.事件6.3.读值 EdgeX Foundry # E…

JavaEE进阶篇 (一) -- Maven

写在前&#xff1a;Hello各位小伙伴们&#xff0c;这一部分主要对JavaEE进阶部分内容进行学习记录&#xff0c;关于前面学习的内容也会同步更新~~ 在学习新内容之前&#xff0c;需要了解一下基础的内容&#xff1a; JavaEE(Java Platform Enterprise Edition),Java平台企业版&…