【Spring】7.深入理解Spring MVC:从基础概念到高级特性的全面解析

devtools/2024/9/18 6:40:41/ 标签: spring, mvc, java, 后端, spring boot, 数据库

Spring MVC是Spring框架的一个模块,全称为Spring Model-View-Controller,是一个基于Java的实现MVC(Model-View-Controller)设计模式的请求驱动类型的轻量级Web框架。MVC模式是一种用于将应用程序分为三个核心组件的软件设计模式,以便分离内聚关注点,从而使得开发、测试和维护更加容易。

一.基本概念

  • Model(模型):负责数据和业务逻辑,即数据的增删改查等操作。
  • View(视图):负责展示数据(模型)并且可以提供用户交互的界面,通常是指用户看到的界面。
  • Controller(控制器):接收用户请求并将其委托给Model和View去处理,Controller本身不输出任何东西和做任何处理,它只是接收请求并决定调用哪个Model构件去处理请求,然后再确定用哪个View来显示返回的数据。

二.作用

在Web应用中,Spring MVC的作用主要体现在以下几个方面:

  1. 解耦:将视图层和业务逻辑层分离,提高代码的可维护性。
  2. 灵活的视图支持:支持多种视图技术,如JSP、FreeMarker、Thymeleaf等,允许开发者根据项目需求灵活选择。
  3. 请求驱动:以请求为中心,通过注解或配置将请求映射到对应的处理器(Controller中的方法)。
  4. 支持RESTful:支持RESTful风格的Web服务开发,简化了API的创建。
  5. 集成Spring生态:作为Spring大家族的一部分,Spring MVC能够无缝集成Spring的其他模块,如Spring Security、Spring Data等。
  6. 组件化:通过DispatcherServlet、HandlerMapping、ViewResolver等组件,提供了一个完整的请求处理流程。

三.工作流程

Spring MVC的工作原理大致如下:

  1. 用户发送请求到服务器,这个请求首先被DispatcherServlet(前端控制器)捕获。
  2. DispatcherServlet将请求委托给HandlerMapping,由它解析请求并映射到相应的Controller
  3. Controller执行业务逻辑后,返回一个ModelAndView对象,其中包含模型数据和要渲染的视图。
  4. HandlerAdapterModelAndView传递给DispatcherServlet
  5. DispatcherServletModelAndView传递给ViewResolver
  6. ViewResolver解析视图逻辑名,找到具体的视图实现。
  7. 视图将模型数据渲染成HTML,响应给客户端。

Spring MVC通过组件化和注解化的方式,简化了Web应用的开发过程,提高了开发效率和应用的可维护性。

Spring MVC的常用注解可以分为以下几类,每类都包含了注解的作用、使用案例以及使用时需要注意的事项:

四.常用注解

控制器定义注解

  • @Controller

    • 作用:标识该类是一个Spring MVC控制器。
    • 使用案例
      java">@Controller
      public class MyController {@GetMapping("/greeting")public String sayHello() {return "greeting";}
      }
      
    • 注意:控制器中的方法通常设计为线程安全的无状态方法。
  • @RestController

    • 作用:组合了@Controller@ResponseBody,用于类上,意味着该类中的所有方法都默认带有@ResponseBody效果,直接返回数据。
    • 使用案例
      java">@RestController
      public class MyRestController {@GetMapping("/greeting")public String sayHello() {return "Hello, World!";}
      }
      
    • 注意:通常用于RESTful Web服务,无需返回视图。

请求映射注解

  • @RequestMapping

    • 作用:将HTTP请求映射到特定的方法上。
    • 使用案例
      java">@Controller
      public class MyMappingController {@RequestMapping(value = "/hello", method = RequestMethod.GET)public String sayHello(Model model) {model.addAttribute("message", "Hello, Spring MVC!");return "hello";}
      }
      
    • 注意:可以指定请求方法和路径,也可以有额外的属性如请求参数或请求头。
  • @GetMapping, @PostMapping, @PutMapping, @DeleteMapping

    • 作用:分别用于处理GET、POST、PUT、DELETE请求的简便方式。
    • 使用案例
      java">@RestController
      public class MyRestfulController {@GetMapping("/users/{id}")public User getUserById(@PathVariable Long id) {// 返回用户信息return userService.findById(id);}
      }
      
    • 注意:它们是@RequestMapping的特化,限制了HTTP请求类型。

请求参数注解

  • @RequestParam

    • 作用:将请求参数与方法参数绑定。
    • 使用案例
      java">public String searchByKeyword(@RequestParam String keyword, Model model) {// 根据关键词进行搜索model.addAttribute("results", searchService.search(keyword));return "search-results";
      }
      
    • 注意:可以指定请求参数是否是必需的,默认值是什么。
  • @PathVariable

    • 作用:从URI路径模板中提取变量。
    • 使用案例
      java">public String getUserDetails(@PathVariable("username") String username, Model model) {// 根据用户名获取用户详情model.addAttribute("user", userService.findByUsername(username));return "user-details";
      }
      
    • 注意:通常与@RequestMapping一起使用,用于RESTful URI设计。

请求体注解

  • @RequestBody

    • 作用:允许将请求正文中的数据绑定到方法参数上。
    • 使用案例
      java">@PostMapping("/users")
      public User createUser(@RequestBody User user) {// 创建用户return userService.create(user);
      }
      
    • 注意:常用于接收JSON格式的请求体,需要配置适当的转换器。
  • @ResponseBody

    • 作用:指示方法的返回值作为HTTP响应正文返回。
    • 使用案例
      java">@GetMapping("/users/{id}")
      public User getUserById(@PathVariable Long id) {// 获取用户信息return userService.findById(id);
      }
      
    • 注意:通常用于RESTful Web服务,返回值将被序列化为JSON或XML。

异常处理注解

  • @ExceptionHandler
    • 作用:用于全局或特定异常的处理。
    • 使用案例
      java">@ControllerAdvice
      public class GlobalExceptionHandler {@ExceptionHandler(NotFoundException.class)public ResponseEntity<String> handleNotFoundException() {return ResponseEntity.notFound().build();}
      }
      
    • 注意:可以捕获并处理控制器中抛出的异常。

数据注解

  • @ModelAttribute
    • 作用:用于将请求参数或Session中的对象绑定到模型中。
    • 使用案例
      java">public String showForm(@ModelAttribute("user") User user) {// 显示表单return "user-form";
      }
      
    • 注意:可以用于表单数据的初始化。

安全性注解

  • @CrossOrigin
    • 作用:用于跨域资源共享。
    • 使用案例
      java">@RestController
      @CrossOrigin(origins = "http://localhost:4200")
      public class MyRestController {// ...
      }
      
    • 注意:应谨慎使用,以避免开放不受限制的外部访问。

@ControllerAdvice@RestControllerAdvice

  • 作用:定义全局的控制器增强功能,如异常处理器、数据预处理等。
  • 使用案例
    java">@ControllerAdvice
    public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public ResponseEntity<String> handleException(Exception e) {// 全局异常处理逻辑}
    }
    
  • 注意:可以集中处理全局的控制器相关事宜。使用全局注解时,需要注意它们之间的相互影响,确保全局配置符合应用程序的整体架构和设计原则。此外,全局配置的更改可能会影响到整个应用程序的行为,因此在进行全局配置时需要谨慎。

这些注解的组合使用,为Spring MVC应用程序提供了强大的请求映射能力和数据处理能力。在使用过程中,应根据实际需求和最佳实践来选择和配置注解,以确保应用程序的安全性和高效性。

五.异常处理机制

Spring MVC的异常处理机制是一种强大且灵活的错误处理方式,允许开发者捕获和处理应用程序中的异常,以提供更友好的反馈给客户端。以下是Spring MVC处理异常的详细解释和如何自定义异常处理器的步骤:

处理异常的基本流程

  1. 异常抛出

    • 当Spring MVC中的Controller处理方法执行业务逻辑时,如果遇到任何问题导致异常被抛出,该异常会被Spring MVC框架捕获。
  2. 查找异常处理器

    • Spring MVC会查找是否有匹配的异常处理器可以处理这个异常。异常处理器是带有@ExceptionHandler注解的方法。
  3. 执行异常处理器

    • 如果找到合适的异常处理器,Spring MVC会调用该处理器中的相关方法来处理异常。
  4. 返回错误响应

    • 异常处理器负责生成一个适当的响应,可以是一个错误页面、一个JSON对象、一个HTML字符串,或者任何其他类型的响应体。
  5. 无匹配的异常处理器

    • 如果没有找到匹配的异常处理器,Spring MVC将使用其默认的异常处理策略。

自定义异常处理器

  1. 定义异常处理器类

    • 创建一个新的类,使用@ControllerAdvice注解来声明这是一个异常处理器类。这个类可以捕获所有Spring MVC控制器抛出的异常。

      java">@ControllerAdvice
      public class GlobalExceptionHandler {// 这里可以定义异常处理方法
      }
      
  2. 定义异常处理方法

    • 在异常处理器类中定义方法,使用@ExceptionHandler注解指定可以处理的异常类型。

      java">@ExceptionHandler(MethodArgumentNotValidException.class)
      public ResponseEntity<String> handleValidationException(MethodArgumentNotValidException ex) {// 构建并返回一个包含验证错误信息的响应实体String errorMessage = "Validation failed: " + ex.getBindingResult().toString();return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorMessage);
      }
      
  3. 处理方法的返回值

    • 异常处理方法可以返回多种类型的值,如ModelAndViewViewStringResponseEntity等。
  4. 配置异常处理顺序

    • 如果有多个异常处理器可以处理同一个异常,可以通过@Order注解或实现Ordered接口来指定处理顺序。
  5. 使用ResponseEntity

    • 使用ResponseEntity可以自定义响应的状态码、头部信息以及响应体。
  6. 全局与局部异常处理器

    • @ControllerAdvice可以用于全局异常处理,也可以限制在特定的包或控制器上使用@Profile@Component注解来定义局部异常处理器。
  7. 异常处理的响应体

    • 对于@RestController@RestControllerAdvice注解的类,异常处理方法的返回值会直接作为响应体返回,无需显式使用@ResponseBody注解。
  8. 自定义异常

    • 可以创建自定义异常类,使得异常处理器能够更精细地处理特定的业务场景。
  9. 日志记录

    • 在异常处理方法中,可以记录异常日志,便于问题的追踪和调试。

通过自定义异常处理器,可以控制异常信息的呈现方式,提供更友好的错误提示,同时确保API的安全性和稳定性。自定义异常处理器是RESTful API设计中不可或缺的一部分,它提升了用户体验并有助于API的健壮性。

六.高级特性

Spring MVC 提供了一系列高级特性,用以增强应用程序的功能和性能。以下是一些重要的高级特性及其用途、使用方法和注意事项:

拦截器(Interceptor)

用途:拦截器用于在请求处理前后执行通用的处理逻辑,如日志记录、安全验证、事务管理等。

使用案例

java">public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 在请求处理之前执行的操作,如权限检查return true; // 返回 true 表示继续执行请求,返回 false 表示中断请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {// 请求处理之后执行的操作,如统一的响应格式处理}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 请求完成后执行的操作,如资源清理}
}@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**") // 所有路径.excludePathPatterns("/css/**", "/js/**"); // 排除静态资源路径}
}

注意:拦截器可能会影响性能,需要谨慎使用。拦截器的执行顺序可以在注册时指定。

过滤器(Filter)

用途:过滤器用于在请求进入DispatcherServlet之前进行预处理,如日志记录、安全控制、监控等。

使用案例

java">@WebFilter("/*")
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) {// 初始化过滤器}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {// 在请求进入DispatcherServlet之前执行的操作filterChain.doFilter(servletRequest, servletResponse); // 继续过滤器链// 在请求离开DispatcherServlet之后执行的操作}@Overridepublic void destroy() {// 销毁过滤器}
}

注意:过滤器主要用于处理通用的预处理和后处理逻辑,不涉及请求映射。

格式化器(Formatter)

用途:格式化器用于自定义数据的格式化和解析,特别是对于日期、数字等类型的数据。

使用案例

java">public class MyFormatter implements Formatter<Date> {@Overridepublic Date parse(String text, Locale locale) throws ParseException {// 实现字符串到日期的转换逻辑return new SimpleDateFormat("yyyy-MM-dd").parse(text);}@Overridepublic String print(Date object, Locale locale) {// 实现日期到字符串的转换逻辑return new SimpleDateFormat("yyyy-MM-dd").format(object);}
}@Configuration
public class FormatterConfig {@Beanpublic Formatter<Date> dateFormatter() {return new MyFormatter();}
}

注意:格式化器需要注册到Spring MVC的格式化器工厂中,并且与字段的注解结合使用。

异步请求处理

用途:异步请求处理允许应用程序在后台线程中处理长时间运行的任务,而不阻塞请求线程。

使用案例

java">@Controller
public class AsyncController {@RequestMapping(value = "/async", method = RequestMethod.GET)public Callable<String> handleRequest() {return () -> {// 执行耗时操作Thread.sleep(1000); // 模拟耗时操作return "asyncResult";};}
}

注意:异步请求处理需要配置线程池,并且要处理好异常和超时情况。可以使用@Async注解在方法上启用异步执行。

这些高级特性在Spring MVC中发挥着重要作用,它们提供了一种灵活的方式来增强应用程序的功能和性能。在使用这些特性时,需要仔细考虑它们对应用程序的影响,并确保它们被正确配置和使用。

七.Spring MVC与Spring Boot的关系

Spring MVC 和 Spring Boot 的关系可以概括为:

  1. 补充关系:Spring MVC 是 Spring 框架的一部分,专注于 Web 应用的模型-视图-控制器模式。Spring Boot 是一个独立的项目,提供了简化的初始搭建以及开发过程。

  2. 简化配置:Spring Boot 通过自动配置和起步依赖(starters)减少了传统 Spring MVC 应用所需的大量配置。

  3. 集成使用:Spring Boot 并没有取代 Spring MVC,而是与其集成,让开发者可以轻松地在 Spring Boot 应用中使用 Spring MVC。

  4. 快速开发:Spring Boot 鼓励使用约定优于配置的原则,加快了开发速度。

  5. 微服务支持:Spring Boot 与 Spring Cloud 等微服务项目配合,支持构建微服务应用。

在实践中,Spring Boot 应用通常会包含 Spring MVC 作为处理 Web 请求的组件,Spring Boot 提供了对 Spring MVC 的自动配置支持,使得开发者可以快速搭建 RESTful API 或传统的 Web 应用。

Spring MVC作为一个功能强大且灵活的Web框架,为Java开发者提供了构建高效、可维护Web应用的坚实基础。从基础的MVC模式到高级的异步处理和格式化,Spring MVC不断扩展其能力,以适应快速变化的Web开发需求。同时,Spring Boot的出现进一步简化了Spring MVC的应用,让开发者能够更加专注于业务逻辑的实现。


http://www.ppmy.cn/devtools/31729.html

相关文章

2024-05-03 问AI: 在深度学习中,什么叫文字嵌入层

文心一言 在深度学习中&#xff0c;文字嵌入层&#xff08;Word Embedding Layer&#xff09;是神经网络的一个部分&#xff0c;主要用于将离散的文本数据&#xff08;如单词、句子等&#xff09;转换为连续的低维向量表示。这种转换有助于神经网络更好地理解和处理文本数据&a…

给PDF文件加骑缝章的工具

真有这样的工具。以前用各种工具制作过“橡皮图章”&#xff0c;但碰到骑缝章的情况就有些束手无策&#xff0c;主要是太麻烦了。 现在突然发现有人制作和开源这种工具&#xff0c;还有现成的exe文件下载。试用于前几日&#xff0c;不禁称之曰能。 下面是链接和原始的介绍&am…

(最全代码示例)js中常见的数组操作方法有哪些,哪些会修改原数组

JavaScript中常见的数组操作方法有&#xff1a;push、pop、shift、unshift、concat、slice、splice、sort、reverse、join、toString、indexOf、lastIndexOf、forEach、map、filter、reduce、reduceRight。 结论&#xff1a; 会直接修改原始数组有&#xff1a;增2个、删2个、合…

gateway中对返回的数据进行处理

gateway中对返回的数据进行处理 背景1.项目层次 背景 最近公司有个需求是对返回数据进行处理&#xff0c;比如进行数据脱敏。最后在gateway中进行处理。 1.项目层次 根据项目的结构&#xff0c;原本在菜单功能处有对于权限设计的url判断&#xff0c;所以在url后面加了一个正…

二维数组案例

二维数组案例 案例1&#xff1a;定义一个函数&#xff0c;获取某个数组中的最小值 package com.qf.work; public class Work {public static void main(String[] args) {int[] arr {4,6,5,1,8,9,7,3};int min getMin(arr);System.out.println("最小值为&#xff1a;&q…

SSH远程管理服务

什么是SSH服务器&#xff1f; SSH&#xff08;Secure Shell&#xff09;是一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程 复制等功能。SSH 协议对通信双方的数据传输进行了加密处理&#xff0c;其中包括用户登录时输入的用户口令&#xff0c;SSH 为建立在…

【数据库原理及应用】期末复习汇总高校期末真题试卷

试卷 一、填空题 1.________是位于用户与操作系统之间的一层数据管理软件。 2.数据库系统的三级模式结构是指________、________、________。 3.数据库系统的三种数据模型是________ 、________、________。 4.若关系中的某一属性组的值能唯一地标识一个元组&#xff0c;则…

大模型引领NLP研究新范式:从统计机器学习到预训练语言模型

自然语言处理&#xff08;NLP&#xff09;研究范式经历了从浅层到深层、从局部到整体、从特定到通用的演进过程。下面我们来详细回顾这一过程。 一、早期的统计机器学习方法&#xff08;20世纪90年代 - 21世纪初&#xff09; 词袋模型&#xff08;Bag-of-Words&#xff09; 将…

AI项目二十一:视频动态手势识别

若该文为原创文章&#xff0c;转载请注明原文出处。 一、简介 人工智能的发展日新月异&#xff0c;也深刻的影响到人机交互领域的发展。手势动作作为一种自然、快捷的交互方式&#xff0c;在智能驾驶、虚拟现实等领域有着广泛的应用。手势识别的任务是&#xff0c;当操作者做出…

递归实现组合型枚举

#include<bits/stdc.h> using namespace std; int n,m; vector<int> num; void dfs(int k) { //如题解所述 if(num.size() > m || num.size() (n - k 1) < m) return; //到达枚举边界&#xff0c;输出结果并结束 if(k n 1) …

Spring boot + dubbo 项目启动报错 ClassNotFoundException WebServerFactoryCustomizer

1 背景 代码和包依赖等信息没做任何修改&#xff0c;之前项目启动没问题的&#xff0c;有一天项目在测试环境突然启动报错 了&#xff0c;生产环境可以正常启动。报错信息如下所示。 Caused by: java.lang.ClassNotFoundException: org.springframework.boot.web.server.Web…

如何从Mac上的清空垃圾箱中恢复已删除的文件?

Mac用户几乎每天都会删除文件。当您将文档删除到 Mac 垃圾箱时&#xff0c;该文件将被剪切到 Mac 垃圾箱中&#xff0c;并且可以轻松放回原处。但是&#xff0c;在某些情况下&#xff0c;您错误地删除了文档和文件&#xff0c;并在您意识到自己犯了一个大错误之前清空了垃圾箱。…

node.js中的fs模块,读写语法讲解

本文分享node.js的入门知识&#xff0c;使用 fs 模块封装的方法读写文件内容 node中的fs 模块&#xff1a;封装了与本机文件系统进行交互的&#xff0c;方法和属性&#xff0c;使用语法如下&#xff1a; 1、加载 fs 模块&#xff0c;得到 fs 对象 const fs require(fs) 2、…

阿里云API网关 产品的使用笔记

阿里云的产品虽多&#xff0c;还是一如既往的一用一个看不懂&#xff0c;该模块的文档依旧保持“稳定”发挥&#xff0c;磕了半天才全部跑通。 用阿里云API网关的原因是&#xff0c;在Agent中写插件调用API的时候&#xff0c;需要使用Https协议&#xff0c;又嫌搞备案、证书等事…

无人机+快递柜:物资运输技术详解

无人机和快递柜的结合在物资运输技术中展现出了巨大的潜力和优势。这种组合方式充分利用了无人机的灵活性和高效性&#xff0c;以及快递柜的便捷性和安全性&#xff0c;从而实现了物资运输的快速、准确和可靠。 无人机作为物资运输的主要工具&#xff0c;具有以下几个显著的优势…

计算机网络期末试题

第一章 概述 一. 单选题&#xff08;共13题&#xff0c;36.4分&#xff09; 1. (单选题) 因特网起源于( &#xff09;网络。 A. ARPANETB. EthernetC. CATVD. CERNET 我的答案: A:ARPANET;正确答案: A:ARPANET; 2.8分 2. (单选题)人们把( &#xff09;年作为因特网的诞…

牛客热题:两个链表的第一个公共节点

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;两个链表的第一个公共节点题目链…

上海计算机学会2021年4月月赛C++丙组T1巧妙的数

题目描述 如果一个十进制整数能够被它的每一个非零数码整除&#xff0c;则称它为巧妙的数&#xff0c;譬如 102 是一个巧妙的数&#xff0c;因为 102 能被 1 与 2 整除&#xff0c;而 2021 不是&#xff0c;因为它不能被 22整除。给定一个 n&#xff0c;请判定它是否为巧妙的数…

MATLAB 微积分

MATLAB 微积分 MATLAB提供了多种方法来解决微分和积分问题&#xff0c;求解任意程度的微分方程式以及计算极限。最重要的是&#xff0c;您可以轻松求解复杂函数的图&#xff0c;并通过求解原始函数及其导数来检查图上的最大值&#xff0c;最小值和其他文具点。 本章将讨论微…

排序算法(2)快排

交换排序 思想&#xff1a;所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置&#xff0c;交换排序的特点是&#xff1a;将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 一、冒泡排序 public static…