当前位置: 首页 > 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.lryc.cn/news/626430.html

相关文章:

  • 应急响应-模拟服务器挂马后的应急相关操作
  • K8S-Pod资源对象
  • Spring Retry实战指南_让你的应用更具韧性
  • 服务器内存使用buff/cache的原理
  • k8s笔记01
  • 自建开发工具IDE(一)之拖找排版—仙盟创梦IDE
  • 跨域问题解决方法
  • 三分钟速通SSH登录
  • IDEA:控制台中文乱码
  • IDEA切换分支时,提示:Git Checkout Problem
  • 用通俗易懂的语言解释前后端分离和不分离的区别及其优缺点
  • 【Java】深入浅出Spring中的@Autowired:自动注入的奥秘
  • 【数据结构】直接选择排序
  • 九、Java类核心语法:构造器、this、封装与static详解
  • rsync 工具
  • Linux 文本处理三剑客:awk、grep、sed 完全指南
  • Redis 安装教程
  • Linux的i节点(inode) 和 数据块(Block)相关操作详解
  • 中小型企业是否需要使用高防服务器
  • 服务器硬件电路设计之 SPI 问答(三):SPI 信号完整性守护与时钟频率的硬件设计羁绊
  • 阿里云ECS服务器的公网IP地址
  • 服务器硬件电路设计之 SPI 问答(一):解密 SPI—— 从定义到核心特性
  • 对称加密算法
  • TDengine IDMP 运维指南(数据导入导出)
  • AI大模型×政务热线:数造科技打造企业动态画像的“实时监测引擎”
  • 【自记】Power BI 中 DISTINCT 和 ALLNOBLANKROW 的区别说明
  • Java:将视频上传到腾讯云并通过腾讯云点播播放
  • 通过uniapp将vite vue3项目打包为android系统的.apk包,并实现可自动升级功能
  • 【考研408数据结构-04】 栈与队列:受限的线性表
  • CentOS7.9中安装Harbor以及配置https