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

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控制器。
    • 使用案例
      @Controller
      public class MyController {@GetMapping("/greeting")public String sayHello() {return "greeting";}
      }
      
    • 注意:控制器中的方法通常设计为线程安全的无状态方法。
  • @RestController

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

请求映射注解

  • @RequestMapping

    • 作用:将HTTP请求映射到特定的方法上。
    • 使用案例
      @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请求的简便方式。
    • 使用案例
      @RestController
      public class MyRestfulController {@GetMapping("/users/{id}")public User getUserById(@PathVariable Long id) {// 返回用户信息return userService.findById(id);}
      }
      
    • 注意:它们是@RequestMapping的特化,限制了HTTP请求类型。

请求参数注解

  • @RequestParam

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

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

请求体注解

  • @RequestBody

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

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

异常处理注解

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

数据注解

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

安全性注解

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

@ControllerAdvice@RestControllerAdvice

  • 作用:定义全局的控制器增强功能,如异常处理器、数据预处理等。
  • 使用案例
    @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控制器抛出的异常。

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

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

      @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)

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

使用案例

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之前进行预处理,如日志记录、安全控制、监控等。

使用案例

@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)

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

使用案例

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的格式化器工厂中,并且与字段的注解结合使用。

异步请求处理

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

使用案例

@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.mzph.cn/pingmian/6283.shtml

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

相关文章

Java | Leetcode Java题解之第68题文本左右对齐

题目&#xff1a; 题解&#xff1a; class Solution {private String line(List<String> list,int maxWidth,int totalLength,boolean isLast){StringBuilder sb new StringBuilder();sb.append(list.get(0));if(list.size() 1){String ap " ".repeat(maxW…

二维数组的鞍点(C语言)

一、鞍点解释&#xff1b; 鞍点就是该位置上的元素在该行上最大、在该列上最小&#xff1b; 二、N-S流程图&#xff1b; 三、运行结果&#xff1b; 四、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff…

定制开发AI名片商城AI导购系统:引领营销自动化的新时代

在数字营销日新月异的今天&#xff0c;一个革命性的工具——定制开发AI名片商城AI导购系统&#xff0c;正逐渐崭露头角&#xff0c;成为企业私域运营中的得力助手。它不仅仅是一个营销工具&#xff0c;更是一个拥有强大营销自动化能力和先进算法技术的在线助理&#xff0c;为企…

【neteq】tgcall的调用

G:\CDN\P2P-DEV\Libraries\tg_owt\src\call\call.cc基本是按照原生webrtc的来的:G:\CDN\P2P-DEV\tdesktop-offical\Telegram\ThirdParty\tgcalls\tgcalls\group\GroupInstanceCustomImpl.cpptg对neteq的使用 worker 线程创建call Call的config需要neteqfactory Call::CreateAu…

嵌入式物联网系统软硬件基础知识大全(2)

接口技术 1. Flash存储器 (1)Flash存储器是一种非易失性存储器,根据结构的不同可以将其分为NOR Flash和NAND Flash两种。 (2)Flash存储器的特点: A、区块结构:在物理上分成若干个区块,区块之间相互独立。 B、先擦后写:Flash的写操作只能将数据位从1写成0,不能从…

FPGA学习笔记(2)——Verilog语法及ModelSim使用

1.1 语法 1、赋值语句 和 < 为阻塞赋值&#xff0c;当该语句结束时&#xff0c;下一个语句才开始执行&#xff0c;串行执行 < 为非阻塞幅值&#xff0c;该语句和整个语句块同时执行&#xff0c;并行执行 1.2 ModelSim使用 1、修改源文件路径&#xff1a;File -> …

[1702]java旅游资源网上填报系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java旅游资源网上填报系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql…

ES6入门知识

**************************************************************************************************************************************************************************** 0、ES6学习目标 【1】整体目标 ES6的模块化语法 *************************************…

模式识别作业:颜色算子的三种阈值分割算法

一、引言&#xff1a; 在图像处理中&#xff0c;我们往往需要提取图像的一些关键信息&#xff0c;比如本篇文章的内容——提取颜色&#xff0c;然而当我们需要提取某一种颜色时&#xff0c;无论图像余下的部分如何“丰富多彩”&#xff0c;他们都不再重要&#xff0c;需要被忽…

如何使用SSH密钥克隆仓库

1.创建SSH Key 在用户目录下查看有没有.ssh目录。如果有且该.ssh目录下有id_rsa&#xff08;私钥&#xff09;&#xff0c;和id_rse_pub(公钥)这俩文件&#xff0c;那么这一步就可以跳过。否则使用以下指令创建SSH Key ssh-keygen -t rsa -C "xxxqq.com" "xx…

8.k8s中网络资源service

目录 一、service资源概述 二、service资源类型 1.ClusterIP类型 2.service的nodeport类型 3.service的loadbalancer类型&#xff08;了解即可&#xff09; 4.service的externalname类型&#xff08;了解即可&#xff09; 三、nodeport的端口范围设置和svc的endpoint列表 1.修…

AJAX概述和基本使用

01 【AJAX概述和基本使用】 1.AJAX简介 AJAX 全称为Asynchronous JavaScript And XML&#xff0c;就是异步的JS 和XML 通过AJAX 可以在浏览器中向服务器发送异步请求&#xff0c;最大的优势&#xff1a;无刷新获取数据 AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准…

刷代码随想录有感(53):合并二叉树

题干&#xff1a; 代码&#xff08;递归实现&#xff09;&#xff1a; TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {//前序好理解&#xff0c;直接将树覆盖到另一个上面if(root1 NULL)return root2;//当前遍历节点为空的话就让另一个的值覆盖过来if(root2 NUL…

对命令模式的理解

目录 一、场景1、文本编辑器并不是一个好的例子&#xff0c;设备控制器才是2、设备控制器的demo 二、不用命令模式1、代码2、问题 三、使用命令模式1、代码2、当需求变化时2.1 新增代码2.2 优点 四、进一步思考1、省略对Command的建模可以吗&#xff1f;2、命令模式的价值 一、…

GDPU unity游戏开发 碰撞器与触发器

砰砰叫&#xff0c;谁动了她的奶酪让你的小鹿乱撞了。基于此&#xff0c;亦即碰撞与触发的过程。 碰撞器与触发器的区别 通俗点讲&#xff0c;碰撞器检测碰撞&#xff0c;触发器检测触发&#xff0c;讲了跟没讲似的。碰撞器是用来检测碰撞事件的&#xff0c;在unity中&#xff…

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

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

CGAL 网格测地线距离计算

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 网格测地线距离是指在三维网格模型中计算两点之间的最短路径距离,考虑了网格的拓扑结构和几何形状。与传统的欧几里德距离不同,测地线距离考虑了网格的曲面形状,因此更适用于描述三维空间中的距离。 二、实现代码…

docker常用容器启动命令

docker常用容器启动命令 mysql启动redis启动nginx配置文件&启动 mysql启动 docker run -itd --name mysql-test --restartalways -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 mysqlredis启动 docker run -itd --name redis-test --restartalways -p 6379:6379 redisnginx…

蓝桥杯练习系统(算法训练)ALGO-949 勇士和地雷阵

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 勇士们不小心进入了敌人的地雷阵&#xff08;用n行n列的矩阵表示&#xff0c;*表示某个位置埋有地雷&#xff0c;-表示某个…

yolov5-pytorch-Ultralytics训练+预测+报错处理记录

一、前言 玩一段时间大模型&#xff0c;也该回归一下图像识别。本项目用于记录使用基于Ultralytics的yolov5进行目标检测测试。为什么用Ultralytics呢&#xff1f;答案有3 1、其良好的生态&#xff0c;方便我们部署到其它语言和设备上。因此本次测试结论&#xff1a;大坑没有&…