当前位置: 首页 > news >正文

Spring Boot Controller 使用 @RequestBody + @ModelAttribute 接收请求

Spring Boot Controller 使用 @RequestBody + @ModelAttribute 接收请求,前后端应用示例:

前端 vue3:

发送:请求体和请求参数(对象)

// 下载
import { useTokenStore } from "@/stores/token";
import axios from "axios";
import { formatDateTimeToYYYYMMDDHHMMSS } from "@/utils/pubUtils";
function download() {// 获取JWT令牌信息const tokenStore = useTokenStore();// 使用 axios 原始的功能,向后端发送请求,实现文件下载axios({// 请求方式method: "post",// 请求路径,因为夸域了(前端5173,后端8080),不能直接请求访问 http://localhost:8080/originalRecord/download// url: "http://localhost:8080/originalRecord/download",// 请求路径,因为有代理设置(详情查看vite.config.ts),最终是请求访问 http://localhost:8080/originalRecord/downloadurl: "/api/originalRecord/downloadFile",// 请求标头headers: {// JWT令牌信息Authorization: tokenStore.token},// 请求体,后端 spring boot 需要使用 @RequestBody 接收data: props.detailDatas,// 请求参数,请求参数是一个对象,后端 spring boot 可以使用 @ModelAttribute 接收,推荐使用。// 也可以使用多个 @RequestParam 接收(如果对象属性有十几个,那么就需要十几个 @RequestParam 接收,这样应用很麻烦,不推荐)params: resultTempletTableCurrentRow.value,// 响应类型为 blob,用于接收二进制数据流responseType: "blob"}).then((response) => {// 获取响应标头的内容类型content-type属性// @ts-ignore 忽略 null 报错let contentType = response.headers.getContentType();// 正常返回的是application/octet-stream,八位字节的二进制数据流if (contentType === "text/html") {ElMessage.error("请求无效,下载失败!");return;}// 从响应标头中获取 content-disposition 属性的信息const contentDisposition = response.headers["content-disposition"];// 设置下载文件默认名称let fileName = "原始记录" + formatDateTimeToYYYYMMDDHHMMSS() + ".xls";// content-disposition 有内容if (contentDisposition) {// 通过正则表达式解析出文件名称,数据示例:['filename=Info.xlsx', 'Info.xlsx', '', index: 11, input: 'attachment;filename=Info.xlsx', groups: undefined]const matchArray = contentDisposition.match(/filename=(.*?)(;|$)/);if (matchArray && matchArray.length > 1) {// 获取文件名称(索引为1的元素内容)fileName = decodeURIComponent(matchArray[1]);}}// 将接收到的响应消息体的内容(二进制数据流)result.data,创建为 Blob 对象,用于对文件的操作const blob = new Blob([response.data], { type: response.headers["content-type"] });// 将响应消息体的内容(二进制数据流)转换为url地址对象const objectUrl = URL.createObjectURL(blob);// 创建链接标签<a></a>const a = document.createElement("a");// 设置链接路径a.href = objectUrl;// 设置下载的文件名称// a.setAttribute("download", fileName);a.download = fileName;// 增加链接标签document.body.appendChild(a);// 模拟点击链接标签,下载文件a.click();// 移除链接标签document.body.removeChild(a);// 移除url地址对象,释放资源URL.revokeObjectURL(objectUrl);}).catch((error) => {ElMessage.error("下载失败!" + error);});
}

后端:

接收:@RequestBody接收请求体,@ModelAttribute接收请求参数(对象)

/*** 下载文件(原始记录excel文件),实现从服务器文件系统(文件目录)中下载文件* &#064;RequestParam  只能用于绑定简单的数据类型(如 String、int、boolean 等),而不能直接绑定到一个对象。* &#064;ModelAttribute  可以将多个请求参数绑定到一个对象,会自动将请求参数映射到对象的字段上。* @param sampleItemRecordList 样品项目记录列表 {@link List}&lt;{@link SampleItemRecord}&gt;* @param recordTemplet 结果模板对象 {@link ResultTemplet}* @return 文件数据流 {@link ResponseEntity}&lt;{@link Resource}&gt;*/@PostMapping("/downloadFile")public ResponseEntity<Resource> downloadFile(@RequestBody List<SampleItemRecord> sampleItemRecordList,@ModelAttribute ResultTemplet recordTemplet){log.info("【原始记录打印】,下载,实现从服务器文件系统(文件目录)中下载文件,/originalRecord/downloadFile," +"sampleItemRecordList = {},recordTemplet = {}", sampleItemRecordList, recordTemplet);try {// 生成原始记录文件,返回文件路径String path = originalRecordService.createRecordFile(sampleItemRecordList, recordTemplet);log.info("【原始记录打印】,生成文件路径:{}", path);// 创建文件路径Path filePath = Paths.get(path);// 创建资源Resource resource = new UrlResource(filePath.toUri());// 资源存在 或者 可读if (resource.exists() || resource.isReadable()) {// 返回响应实体return ResponseEntity// 设置状态.ok()// 设置内容类型为 MediaType.APPLICATION_OCTET_STREAM,八位字节的二进制数据流.contentType(MediaType.APPLICATION_OCTET_STREAM)// 设置响应标头,添加属性 Content-Disposition,Content-Disposition就是当用户想把请求所得的内容存为一个文件的时候提供一个默认的文件名。// 其属性值必须要加上attachment,如: attachment;filename="name.xlsx",就是文件名称的信息,并且文件名称需要用双引号包裹(不支持中文编码,需要编码转换)// 设置内容处置为附件,并指定文件名,到时前端就可以解析这个响应头拿到这个文件名称进行下载// .header("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(fileName, StandardCharsets.UTF_8) +"\"")// 实际测试发现文件名称不用双引号包裹,也是可以达到需求目标,并且前端通过正则表达式解析出文件名称时还简单一些.header("Content-Disposition", "attachment;filename=" +URLEncoder.encode(PublicUtils.getFileName(path), StandardCharsets.UTF_8))// 设置响应消息体为 resource.body(resource);} else {// 文件没有找到return ResponseEntity.notFound().build();}} catch (Exception e) {// 文件下载失败return ResponseEntity.internalServerError().build();}}

@ModelAttribute是 Spring MVC 框架中的一个核心注解,主要用于数据绑定、模型管理和预处理逻辑。其作用可分为以下三类,结合具体场景和代码示例说明如下:


一、​​绑定请求参数到命令对象​

  • ​作用​​:将 HTTP 请求参数(如表单字段、查询参数)自动绑定到方法参数的对象上,简化数据提取和封装流程。

  • ​示例​​:

    java

    下载

    复制

    运行

    @PostMapping("/submit") public String submitForm(@ModelAttribute User user) { // 自动将请求参数绑定到User对象的属性(如user.name、user.age) return "result"; }

    • Spring 会根据请求参数名与对象属性名匹配,自动填充数据

      2

      3

  • ​适用场景​​:表单提交、RESTful API 参数接收。


二、​​初始化模型数据(预处理)​

  • ​作用​​:在控制器方法执行前,向模型(Model)中添加共享数据或初始化对象,供后续请求处理方法或视图使用。

    • ​方法级别​​:

      java

      下载

      复制

      运行

      @ModelAttribute("allRoles") public List<String> populateRoles() { return Arrays.asList("Admin", "User"); // 数据自动添加到Model中 }

      • 该方法会在同一控制器内所有 @RequestMapping方法前执行

        1

        5

    • ​类级别​​:通过 @ControllerAdvice实现全局模型属性共享

      4

  • ​适用场景​​:

    • 预加载下拉框选项(如角色列表)

      2

    • 表单回显时初始化对象(如编辑页面加载数据库数据)

      3

      5


三、​​暴露返回值到模型​

  • ​作用​​:将方法返回值直接作为模型属性,无需显式调用 Model.addAttribute()

  • ​示例​​:

    java

    下载

    复制

    运行

    @GetMapping("/edit/{id}") @ModelAttribute("user") // 返回值以"user"为属性名加入Model public User loadUser(@PathVariable Long id) { return userService.findById(id); }

    • 视图层可直接通过 ${user}访问该对象

      3

      5


四、​​高级特性与注意事项​

  1. 1.

    ​命名规则​​:

    • 默认以类名首字母小写作为属性名(如 User→ user),可通过 @ModelAttribute("customName")自定义

      5

  2. 2.

    ​与 @SessionAttributes结合​​:

    • 实现跨请求的模型数据持久化(如多步骤表单)

      3

  3. 3.

    ​性能优化​​:

    • 避免在 @ModelAttribute方法中执行耗时操作,因其会在每次请求前触发

      1

      4


总结

@ModelAttribute的核心价值在于:

  1. 1.

    ​简化数据绑定​​:自动封装请求参数到对象。

  2. 2.

    ​统一预处理​​:集中管理模型数据初始化。

  3. 3.

    ​增强可维护性​​:减少重复代码,提升架构清晰度

    1

    4

    5

具体用法需根据业务场景选择,如简单表单绑定用参数注解,复杂预处理用方法级别注解。

http://www.dtcms.com/a/341119.html

相关文章:

  • 车联网(V2X)中万物的重新定义---联网汽车新时代
  • Dubbo 的 Java 项目间调用的完整示例
  • 分析NeRF模型中颜色计算公式中的参数
  • Paraformer实时语音识别中的碎碎念
  • RuntimeError: Dataset scripts are no longer supported, but found wikipedia.py
  • 车辆订单状态管理的优化方案:状态机设计模式
  • 从ioutil到os:Golang在线客服聊天系统文件读取的迁移实践
  • 从零开发Java坦克大战Ⅱ(上) -- 从单机到联机(架构演进与设计模式剖析)
  • 音频大模型学习笔记
  • CS+ for CC编译超慢的问题该如何解决
  • 0-1 背包问题(模板)
  • 汽车ECU实现数据安全存储(机密性保护)的一种方案
  • Ubuntu apt安装nginx
  • 使用Spring Retry组件优雅地实现重试
  • Java 定时任务 - 从基础到高阶使用 - 从 Timer 到 Quart
  • 数据结构 二叉树 二叉树链式结构的实现
  • 数据分析师常用命令
  • 数据结构中的列表:深度解析数组与链表的实现与抉择
  • PyTorch API 3 - distributed
  • 前后端联合实现文件上传,实现 SQL Server image 类型文件上传
  • 51单片机-驱动LED点阵模块教程
  • SQL-leetcode—3374. 首字母大写 II
  • Docker--安装MySQL、Redis
  • 面试常考的 SQL 窗口函数汇总
  • 【Tech Arch】Apache Pig大数据处理的高效利器
  • 深入理解数据结构:从数组、链表到B树家族
  • 数据结构:利用旋转在AVL树中维持平衡(Inserting in AVL with Rotation)
  • FastAPI初学
  • PyTorch API 1
  • 新能源知识库(81)新能源半实物仿真平台介绍