民启特种作业 · 安阳新乡特种作业考证咨询

首页 安阳报考专题 新乡报考专题 报名流程 考试批次 低压电工作业 熔化焊接与热切割 高处安装维护拆除 叉车司机 塔吊司机 新闻资讯 证书查询核验 证书复审 企业团报 在线预约 关于我们 联系我们
电话咨询 18236992212
首页新闻资讯文章详情

资讯详情

考试通知、政策法规、备考经验、行业动态,为安阳、新乡特种作业考证人员提供信息参考。

首页新闻资讯Spring Boot 接口参数接收全攻略:GET 与 POST 从原理到实战

Spring Boot 接口参数接收全攻略:GET 与 POST 从原理到实战

2026/10/12 2:58:10 民启特种作业 安阳 · 新乡考证资讯
Spring Boot 接口参数接收全攻略:GET 与 POST 从原理到实战 身边刚开始写 Spring Boot 的后端同学问得最多的往往不是某个组件怎么用而是“接口到底怎么收参数”。明明前端把参数传回来了后端却报 400或者收到的全是 null。这个问题看似基础却几乎每天都在重复出现。今天这篇就从 GET 请求和 POST 请求两条线出发把 Spring Boot 接收参数的常见方式、底层逻辑和实操中容易踩的坑一次说清楚。不管你是在校写课程设计还是刚转 Java 后端或者前端同学想搞明白后端接口为什么“不认”你的参数这篇都适用。1. GET 和 POST 的差异决定了参数怎么传1.1 先从 HTTP 报文说起理解参数接收得先回到 HTTP 本身。一次请求其实由三部分构成请求行、请求头、请求体。请求行里包含方法、路径和协议版本比如GET /api/user?nameTomage18 HTTP/1.1同样一个地址如果是 POST请求体可能长这样POST /api/user/add HTTP/1.1 Content-Type: application/json {name:Tom,age:18}Spring Boot 的接口层接收参数本质就是从请求行、URL、请求头、请求体的不同位置把数据取出来再根据方法签名上的注解去映射。搞不清数据在哪一层接收参数就是猜谜。很多新手容易把“URL 里的问号后面那串”当成请求体其实不是。?nameTom这段在 HTTP 规范里被称为 query string也就是查询字符串它属于请求目标的一部分。真正的请求体只有在 POST 等方法中才有而且必须依赖Content-Type告诉服务器怎么解析。1.2 GET 和 POST 的参数落在哪里GET 请求的参数绝大多数情况都放在 URL 里具体有两种形式一种是 query string就是?keyvalue这种键值对另一种是路径本身的一部分比如/user/123里的123。两种都能被 Spring MVC 接收只是注解不同。POST 请求的参数位置就灵活得多。传统网页表单默认提交的格式是application/x-www-form-urlencoded参数放在请求体里但编码方式跟 URL 后面的 query string 很相似。现代前后端分离项目更多用application/json参数是纯 JSON 字符串。文件上传则用multipart/form-data。还有一种情况POST 请求也可以带上 query string 或路径变量这在 RESTful 风格的更新、删除接口中很常见。也就是说POST 请求的参数可能在三个地方URL 后面的 query、路径中的动态片段、请求体。Spring Boot 接收参数的方式也必须按“参数来源”来选而不是按“GET 还是 POST”粗暴划分。1.3 为什么 Spring Boot 要区分这些场景Spring MVC 设计了一整套参数解析机制。接口方法上写了RequestParam、PathVariable、RequestBody这些注解后框架会在调用方法前通过HandlerMethodArgumentResolver把所有参数解析好再注入到方法签名里。你写的代码只是在“声明参数从哪来”真正干活的是框架底层那套解析器。理解这一层对排查问题特别有帮助。比如方法签名写的是RequestBody UserDTO dto但前端发的是application/x-www-form-urlencoded框架就会直接抛HttpMediaTypeNotSupportedException表现为 415。如果你不知道这是“请求体格式和接口声明不匹配”大概率会在业务代码里找半天。2. GET 请求接收参数的常用打法2.1 RequestParam最基础也最容易踩坑先看最典型的场景query string 接收单个参数GetMapping(/api/user) public String getUser(RequestParam(name) String name) { return name name; }请求curl http://localhost:8080/api/user?nameTomname就会拿到Tom。如果 URL 里的参数名和方法参数名相同RequestParam可以不写括号里的 value但我还是建议写清楚。原因很简单代码可读性更好而且将来 refactor 改方法参数名时不会把接口契约一起改坏。这个注解有三个属性要记住required默认是true所以缺少参数时直接报 400defaultValue可以设置默认值只要设了默认值required实际上就变成 false 了value指定前端传的参数名。举个例子GetMapping(/api/user) public String getUser( RequestParam(name) String name, RequestParam(value age, required false, defaultValue 18) Integer age) { return name : age; }这里age没传时自动是 18。注意一点如果前端传的年龄是abcSpring 在尝试把字符串转成Integer时会抛类型转换异常同样表现为 400。所以不要以为有了defaultValue就万事大吉类型不对照样挂。2.2 PathVariableREST 风格路径里的动态参数你经常看到这样的接口/user/{id}。{id}就是路径变量。后端这样接收GetMapping(/api/user/{id}) public String getUserById(PathVariable(id) Long id) { return id id; }请求curl http://localhost:8080/api/user/1001id就是 1001。路径变量和 query string 最大的区别在于它表达的是“资源的标识”而不是“筛选条件”。比如/user/1001表示查询 ID 为 1001 的用户而/user?nameTom表示按名字搜索。一个容易忽略的坑如果你的方法参数名和路径变量名一致比如方法签名写成(PathVariable Long id)依赖的是编译时的参数名保留。用 IDEA 开发时一般没问题因为 IDEA 默认会给编译参数加-parameters。但如果你用 Maven 直接在命令行打包而pom.xml里没有配置parameters项老版本的 JDK 编译可能把参数名变成arg0启动后就会报“找不到名为 id 的路径变量”。建议要么老老实实写上PathVariable(id)要么在 Maven 插件里开启-parameters。路径变量还支持简单正则约束比如只允许数字GetMapping(/api/user/{id:[0-9]})这样/api/user/abc会直接 404而不是进入方法后再报类型转换错误。2.3 POJO 对象绑定查询条件多的时候这么写查询接口经常有十几个筛选条件分页、排序、关键字、时间范围。如果全用RequestParam往方法签名里写参数十几行看起来非常痛苦。Spring MVC 支持把 query string 的参数自动绑定到一个普通 Java 对象的属性上。GetMapping(/api/user/search) public ListUser search(UserQuery query) { return userService.search(query); }UserQuery是这样public class UserQuery { private String keyword; private Integer page; private Integer size; public String getKeyword() { return keyword; } public void setKeyword(String keyword) { this.keyword keyword; } // 其他 getter/setter 省略 }请求curl http://localhost:8080/api/user/search?keywordTompage1size10框架会自动调用setKeyword(Tom)、setPage(1)、setSize(10)把参数填进对象里。整个过程基于 JavaBean 规范所以必须要有无参构造和对应属性的 setter。这里有个很常见的坑前端用下划线命名比如user_name而后端字段是驼峰userName两者对不上时字段就是 null。Spring 的数据绑定不会帮你自动做驼峰和下划线的转换。我的建议是接口参数层面统一约定一种命名风格要么都驼峰要么都下划线然后在前端和后端之间把规范定死省得两边互相迁就。2.4 Map 和动态参数不确定参数名时的兜底方案有些场景下参数名是不固定的比如透传参数给第三方、报表筛选条件动态拼接。这时可以用 Map 兜底GetMapping(/api/params) public String getParams(RequestParam MapString, String params) { return params.toString(); }请求?a1b2c3Map 里就是这三对键值。这个方案适合参数名不确定的前端组件但有一个明显的弊端如果同一个参数名传了多个值比如?tagjavatagspringMapString, String只会保留一个。想接多值要么用MultiValueMap类型要么用ListString比如GetMapping(/api/tags) public String getTags(RequestParam ListString tag) { return tag.toString(); }这种写法下?tagjavatagspring会得到[java,spring]。实际项目里我通常不喜欢用 Map 当接口参数因为它会丢失类型、难以校验、文档也不清晰更推荐为明确的业务场景定义 POJO。只有在做转发、网关这类通用组件时Map 才有优势。3. POST 请求接收参数的完整形态3.1 表单提交x-www-form-urlencoded传统表单提交是 POST 请求最常见的形态之一。前端把参数编码成keyvaluekey2value2的格式请求头Content-Type是application/x-www-form-urlencoded。后端接收时可以继续使用RequestParam也可以直接把参数绑到 POJO 上逻辑和 GET 的 query string 几乎一样。PostMapping(/api/user/form) public String createUser(UserForm form) { return form.getName() : form.getAge(); }UserForm里放name、age字段和对应的 setter 就可以。区别在于GET 的参数在 URL 中POST 的参数在请求体中但 Spring MVC 的参数绑定处理逻辑是同一套。这里有一个容易犯的错有些人以为表单数据也是 JSON于是在 POST 接口上用RequestBody去接结果前端 Content-Type 是application/x-www-form-urlencoded后端立刻报 415。反过来如果前端发的是 JSON而后端用RequestParam接所有参数都会是 null。我在联调现场几乎每周都能看到这种错位问题根源就是前后端对请求体格式的认知不一致。3.2 JSON bodyRequestBody 详解前后端分离项目最常见的 POST 接口是接收 JSON 字符串。后端这样写PostMapping(/api/user/json) public User createUser(RequestBody UserDTO dto) { return userService.create(dto); }UserDTO就是一个普通类比如public class UserDTO { private String name; private Integer age; // getter/setter 省略 }前端发请求时必须把Content-Type设置为application/jsonbody 传{name:Tom,age:18}Spring 会调用 Jackson 做反序列化把 JSON 转成UserDTO对象。RequestBody有几个隐藏行为必须知道。第一它默认也是必需的如果请求体为空会抛HttpMessageNotReadableException表现成 400。第二它的解析不再走 JavaBean setter 那一套而是完全由 JSON 序列化框架通常是 Jackson控制。第三如果 JSON 里包含后端不认识的字段在 Spring Boot 默认配置下会直接反序列化失败报 400想忽略未知字段需要在全局或类上配置。JSON 接收特别容易在日期字段上出问题。比如 DTO 里有个LocalDate birthDate前端传1999-01-01没问题但如果传1999/01/01Jackson 默认不认这个格式。处理方式是在字段上加JsonFormat(pattern yyyy-MM-dd)或者全局配置 ObjectMapper。这个问题放到第四章再来细说。3.3 文件上传multipart/form-data 的混合参数文件上传必须用multipart/form-data。此时请求体不再是单纯的 JSON而是多个“part”组成每个 part 有自己的标题和内容文件 part 的内容是二进制。Spring Boot 里这样接收PostMapping(/api/upload) public String upload(RequestParam(file) MultipartFile file, RequestParam(note) String note) { return file.getOriginalFilename() : note; }这种场景下依然用RequestParam而不是RequestBody。MultipartFile是 Spring 对上传文件的封装提供了getOriginalFilename()、getSize()、getInputStream()等方法。文件上传有几个配置需要特别留意。Spring Boot 默认单文件最大 1MB总请求最大 10MB超过就会报MaxUploadSizeExceededException。修改配置很简单spring.servlet.multipart.max-file-size20MB spring.servlet.multipart.max-request-size50MB还有一个联调中的坑前端用 FormData 上传文件时如果note字段放在文件之前或之后后端用户如果用commons-fileupload那套老写法会容易出问题但 Spring Boot 内嵌的StandardServletMultipartResolver对多 part 的顺序不敏感所以只要字段名对得上就行。3.4 路径变量 JSON 混合真实接口怎么搭现实中的 RESTful 接口经常是“路径里带 IDbody 里放业务字段”。比如修改用户信息PutMapping(/api/user/{id}) public User updateUser(PathVariable(id) Long id, RequestBody UserDTO dto) { return userService.update(id, dto); }这里PathVariable取路径中的idRequestBody取 JSON 中的业务数据。两者可以共存互不干扰。GET、POST、PUT、DELETE 也都支持这种组合。需要注意如果你的接口方法签名是“路径变量 表单参数”比如PostMapping(/api/user/{id}/form)同时用PathVariable和表单 POJOSpring 也能正确解析因为各自的参数解析器是独立工作的。我们在日常接口设计中应当保持这种一致性资源标识放路径操作数据放 body过滤条件放 query。4. 常见报错与排查实录4.1 400、404、405先分清是哪一类错误遇到过三个 HTTP 状态码对应的原因完全不同。400 Bad Request最常见的之一是“缺少必填参数”。比如接口写了RequestParam(name) String name前端没传nameSpring 抛MissingServletRequestParameterException响应 400。控制台日志里会明确写Required request parameter name for method parameter type String is not present。这时候不要怀疑业务逻辑纯粹是参数没传到位。404 更多是路径没对上。比如接口定义的是/api/user/{id}你请求/api/user且没有映射另一个无参方法自然找不到处理器。还有前面说的路径变量正则约束{id:[0-9]}遇到非数字也会 404。405 是方法不匹配。接口映射了PostMapping(/api/user)但你用 GET 访问Spring 会返回Method Not Allowed。这种问题多见于前端代码里写错 HTTP 方法排查时先看请求方式再对接口注解。4.2 415 和 400请求体解析失败的两种典型415 Unsupported Media Type 意味着服务器理解不了客户端传来的媒体类型。最常见的场景就是后端RequestBody UserDTO dto前端没有设置Content-Type: application/json而是默认用了 text/plain 或 form 格式。解决方法是前端显式加上Content-Type: application/json很多 HTTP 库比如 axios 传对象的时候会自动设置但如果手动拼了字符串就有可能忘记。另外一类 400 是 JSON 解析失败。比如{age:十八}转不了 Integer或者 JSON 字符串本身有语法错误{}括号不匹配。Spring 会抛HttpMessageNotReadableException响应体里的错误信息通常会对定位很有帮助。排查时我一般先拿 curl 单独发一遍请求排除前端代码的干扰看接口本身能不能通。4.3 中文乱码与编码问题GET 请求里带中文必须先做 URL 编码。比如?keyword小明浏览器和 curl 会自动编码成%E5%B0%8F%E6%98%8E但有些客户端库不会自动处理。前端如果在 commit 前用encodeURIComponent就能大大降低服务端收到乱码的概率。Spring Boot 2.x 以后默认请求编码就是 UTF-8所以大多数情况中文没问题。老项目如果用外部 Tomcat 并且没配置 URIEncoding就容易出现 GET 中文乱码。排查时可以用curl -v看请求行里 URL 的编码方式再在接口里把参数打印出来对比一下原始字节。还有一种情况是后端接口返回中文乱码那就要看produces配置了建议明确指定GetMapping(value /api/name, produces application/json;charsetUTF-8)POST 表单中文乱码重点检查应用的过滤器里是否设置了CharacterEncodingFilter并确保forceEncoding为 true。Spring Boot 已经内置了顺序还排在最前面一般不用额外配置但如果你自定义了拦截器小心别把编码过滤器的顺序打乱。4.4 日期、数字、枚举转换失败的实战处理日期转换是最常见的一种。GET 表单参数包括 query string 和 form 表单用DateTimeFormatpublic String findByDate(RequestParam DateTimeFormat(pattern yyyy-MM-dd) LocalDate date) { ... }JSON 里的日期用JsonFormatpublic class DTO { JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private LocalDateTime createTime; }数字转换失败一般是因为字符串里混了空格、逗号或货币符号直接用Integer/Long接收就报错。类型简单时建议在 DTO 里用String接收再做解析和校验这样能给前端更友好的错误提示。枚举转换是个容易被忽略的点。假设 DTO 里有枚举字段UserStatus status前端传ACTIVEJackson 默认用枚举名匹配前端传active就报错。想在接口层做更灵活的映射可以在枚举类上写JsonCreator和JsonValue这算是进阶玩法但联调时早晚会遇到先知道有这回事。5. 写给联调现场的几个建议5.1 参数接收方式的选择原则我自己的习惯是资源 ID 用路径变量查询和过滤用 query string复杂业务数据用 JSON body文件用 multipart。不要在一个接口里什么都混在一起。举个反面例子我曾经见过一个“添加用户”的 POST 接口把用户 ID、用户名、备注全部塞在 query string 里body 只放了一个空 JSON{}。当时为了赶进度大家都这么写结果后续接口文档混乱前端每次调用都要小心翼翼拼 URL。重构之后路径里只留/user创建数据全走 body联调效率明显提升。另一个原则是保持方法的幂等性。GET 不建议用来做删除或修改操作因为 GET 会被缓存、被浏览器预加载、被爬虫访问副作用大的操作放进 POST/PUT/DELETE 更安全。5.2 参数校验别省给前端也提个醒参数接收只是第一步真正有效的接口还要做约束校验。Spring Boot 里可以在 DTO 或表单对象上加校验注解public class UserDTO { NotBlank(message 用户名不能为空) private String name; Min(value 1, message 年龄不能小于1) private Integer age; }然后在接口参数上加Validated或ValidPostMapping(/api/user) public User create(Valid RequestBody UserDTO dto) { ... }对于 GET 的参数如果封装成 POJO同样可以加Valid如果是单独的RequestParamSpring Boot 2.3 需要在类上或方法上配合Validated校验不通过时抛出ConstraintViolationException。实践时我习惯于让前端也做同样的校验后端校验是底线不是用户体验的唯一防线。前端和后端两边的校验规则要保持一致否则会出现“前端提示正常后端一调用就 500”的尴尬局面。5.3 用 curl 模拟各种请求的方法联调时我最常用 curl 而不是图形化工具因为它能精确控制请求行和请求头容易复现线上问题。几个常用示例放这里GET 带 query stringcurl http://localhost:8080/api/user?nameTomage18GET 走路径变量curl http://localhost:8080/api/user/1001POST 表单curl -X POST http://localhost:8080/api/user/form \ -d nameTom \ -d age18POST JSONcurl -X POST http://localhost:8080/api/user/json \ -H Content-Type: application/json \ -d {name:Tom,age:18}POST 文件上传curl -X POST http://localhost:8080/api/upload \ -F file/path/to/test.txt \ -F notehello注意curl 的-d默认会把 Content-Type 设置成application/x-www-form-urlencoded所以发 JSON 时一定要显式加-H。用 Postman 时也要手动检查 body 类型别让工具帮你“猜”。5.4 设计接口时的一些小习惯最后分享几个总结出来的小习惯都是从线上事故里换来的。接口日志里不要打印所有请求参数尤其是有密码、token 的字段。我在项目里曾经因为某个网关把所有 query string 打出来导致登录 token 出现在日志平台吓得当晚就改了日志脱敏逻辑。参数接收区域只负责“接”敏感信息脱敏和审计应该单独处理。对返回给前端的错误信息尽量做一层包装。Spring 默认返回的 400 / 415 报文对前端不友好建议用RestControllerAdvice统一捕获参数异常把“具体哪个参数错了”翻译成中文提示。比如参数类型转换失败时返回“age 必须是数字”比原始异常信息容易理解得多。对日期、金额、枚举这类容易“各写各的”的格式在项目里约定并固化下来。不要一个接口用yyyy-MM-dd另一个用yyyy/MM/dd。我在团队里通常会在接口文档模板里直接写清楚字段格式前端和后端都按模板对齐参数问题至少能减少一半。把 GET、POST 接收参数的方法理清了很多联调问题都能从“玄学”变成“可排查项”。以后遇到接口报错先拆解请求弄清楚参数到底在 URL 里、路径里还是 body 里再看后端注解是否匹配就能快速定位。希望这篇经验能帮你在 Spring Boot 开发的路上少踩几个坑。
特种作业考证资讯 责任编辑:民启特种作业
FUWU BAOZHANG

看完文章,报名服务了解一下

从咨询到拿证,全程有人对接

条件先核对年龄、学历、体检先对照,能报才报
材料免费预审材料拍来先审,不齐的提前补
批次主动提醒报名截止、考试时间提前通知
费用透明费用报名前逐项列明,确认后再办

看完文章还有疑问?

报考条件、材料清单、考试批次,直接电话或在线咨询,几分钟给你明确答复。