小伙伴会不会有疑问:“前端怎么给后端传数据呀?比如我想根据用户 id 查对应的用户信息,该怎么写?” 今天这篇就聚焦 “接收前端参数” 这个核心需求,用 3 个最常用的场景 + 具体案例,手把手教你搞定,看完就能直接用在项目里!
一、先搞懂:前端会怎么传参数
在写代码前,我们先花 2 分钟搞清楚前端给后端传参数的 3 种常见方式,因为不同的传参方式,后端接收的写法不一样:
1. 路径传参(比如http://localhost:8080/user/1)
参数直接拼在 url 路径里,像上面的 “1” 就是用户 id,这种方式适合传单个、简单的参数(比如 id、编号),url 看起来很简洁。
2. 问号传参(比如http://localhost:8080/product?name=手机&price=3000)
参数用 “?” 开头,多个参数用 “&” 分隔,这种方式适合传多个可选参数(比如商品搜索时的名称、价格范围)。
3. 请求体传参(json 格式)
参数放在请求的 “body” 里,不是拼在 url 上,格式是 json,这种方式适合传复杂、多字段的参数(比如用户注册时的姓名、手机号、密码,或者提交订单时的多个商品信息),安全性更高,参数也更灵活。
这 3 种方式覆盖了 90% 以上的开发场景,接下来我们逐个讲解后端怎么接收~
二、准备工作:复用之前的项目和实体类
我们还是在之前的「first-springboot-project」项目里操作,不用新建项目,直接复用已经创建好的:
- 实体类:
user(用户 id、姓名、年龄、手机号)、product(商品 id、名称、价格、库存); - 控制器:可以在之前的
jsoncontroller里加方法,也可以新建paramcontroller(推荐新建,分类更清晰),这里我们选择新建。
先确认项目能正常运行,没有报错~
三、场景 1:路径传参(接收单个参数,如用户 id)
最常见的需求:前端传用户 id(比如 “1”),后端根据 id 查询对应的用户信息并返回。
1. 写接口:用@pathvariable接收路径参数
新建paramcontroller,在里面写一个根据用户 id 查用户的接口:
package com.example.firstspringbootproject.controller;
import com.example.firstspringbootproject.entity.user;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.pathvariable;
import org.springframework.web.bind.annotation.restcontroller;
@restcontroller
public class paramcontroller {
/*
接口1:路径传参——根据用户id查询用户
访问路径:/user/{userid},其中{userid}是占位符,表示这里要传用户id
@pathvariable("userid"):把路径里{userid}的值,赋值给方法参数integer userid
*/
@getmapping("/user/{userid}")
public user getuserbyid(@pathvariable("userid") integer userid) {
// 注意:这里只是模拟查询(实际项目会从数据库查),根据传的userid返回不同用户
if (userid == 1) {
// 返回id为1的用户
return new user(1, "小明", 20, "13800138000");
} else if (userid == 2) {
// 返回id为2的用户
return new user(2, "小红", 19, "13900139000");
} else {
// 没有匹配的用户,返回null(实际项目会返回“用户不存在”的提示)
return null;
}
}
}
2. 关键说明(重点看这 2 处)
- 路径占位符:
@getmapping("/user/{userid}")里的{userid}是 “占位符”,表示这个位置要传参数,参数名可以自己定(比如{id}也可以); - @pathvariable 注解:
@pathvariable("userid")用来 “提取” 路径里占位符的值,括号里的 “userid” 要和路径里{userid}的名称完全一致,然后赋值给后面的integer userid参数。
3. 测试接口(用浏览器或 apifox)
测试 1:查询 id 为 1 的用户
- 浏览器地址栏输入:
http://localhost:8080/user/1; - 返回结果(json):
{"id":1,"name":"小明","age":20,"phone":"13800138000"},正确!
测试 2:查询 id 为 2 的用户
- 输入:
http://localhost:8080/user/2; - 返回:
{"id":2,"name":"小红","age":19,"phone":"13900139000"},正确!
测试 3:查询不存在的 id(比如 3)
- 输入:
http://localhost:8080/user/3; - 返回:
null(符合我们代码里的逻辑)。
四、场景 2:问号传参(接收多个可选参数,如商品搜索)
需求:前端传商品名称(可选)和价格上限(可选),后端根据参数筛选商品列表(比如只传名称 “手机”,就返回所有手机;只传价格上限 3000,就返回所有低于 3000 的商品;两个都传,就返回符合条件的手机)。
1. 写接口:用@requestparam接收问号参数
在paramcontroller里加一个商品搜索接口:
package com.example.firstspringbootproject.controller;
import com.example.firstspringbootproject.entity.product;
import com.example.firstspringbootproject.entity.user;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.pathvariable;
import org.springframework.web.bind.annotation.requestparam;
import org.springframework.web.bind.annotation.restcontroller;
import java.util.arraylist;
import java.util.list;
@restcontroller
public class paramcontroller {
/*
接口2:问号传参——商品搜索(名称和价格上限都是可选参数)
访问路径示例:/product/search?name=手机&maxprice=3000
@requestparam(required = false):表示这个参数是可选的,不传也不会报错
defaultvalue = "": 表示如果参数没传,默认值是空字符串(针对string类型)
*/
@getmapping("/product/search")
public list<product> searchproduct(@requestparam(required = false, defaultvalue = "") string name, @requestparam(required = false) double maxprice) {
//1.创建商品数据库
list<product> productdb = new arraylist<>();
productdb.add(new product(101, "华为手机", 3999.0, 100));
productdb.add(new product(102, "苹果平板", 5999.0, 50));
productdb.add(new product(103, "小米耳机", 299.0, 200));
productdb.add(new product(104, "oppo手机", 2999.0, 80));
// 2. 创建一个空列表,用来装筛选后的商品
list<product> result = new arraylist<>();
// 3. 遍历“商品数据库”,根据参数筛选
for (product product : productdb) {
// 条件1:商品名称包含传入的name(如果name不为空)
boolean matchname = product.getproductname().contains(name);
// 条件2:商品价格小于等于传入的maxprice(如果maxprice不为空)
boolean matchprice = (maxprice == null) || (product.getprice() <= maxprice);
// 两个条件都满足,就加入结果列表
if (matchname && matchprice) {
result.add(product);
}
}
// 4. 返回筛选后的商品列表(spring boot自动转json)
return result;
}
}
2. 关键说明(重点看@requestparam)
required = false:表示这个参数是 “可选的”,前端可以不传(如果不写这个属性,默认是required = true,前端不传就会报错);defaultvalue = "":给参数设置 “默认值”,比如 name 的默认值是空字符串,这样即使前端不传 name,也不会是 null,避免后续代码报错;- 参数名对应:
@requestparam括号里可以写参数名(比如@requestparam("productname")),如果括号里不写,默认会找和方法参数名(比如name)一致的前端参数。
3. 测试接口(多场景测试,更能理解)
测试 1:只传 “商品名称”(搜索 “手机”)
- 访问路径:
http://localhost:8080/product/search?name=手机; - 筛选逻辑:名称包含 “手机”,价格不限制;
- 返回结果:华为手机(3999)和 oppo 手机(2999),正确!
测试 2:只传 “价格上限”(maxprice=3000)
- 访问路径:
http://localhost:8080/product/search?maxprice=3000; - 筛选逻辑:价格≤3000,名称不限制;
- 返回结果:小米耳机(299)和 oppo 手机(2999),正确!
测试 3:两个参数都传(name = 手机 & maxprice=3000)
- 访问路径:
http://localhost:8080/product/search?name=手机&maxprice=3000; - 筛选逻辑:名称包含 “手机” 且价格≤3000;
- 返回结果:只有 oppo 手机(2999),正确!
测试 4:两个参数都不传
- 访问路径:
http://localhost:8080/product/search; - 筛选逻辑:所有商品都符合条件;
- 返回结果:所有 4 个商品,正确!
五、场景 3:请求体传参(接收复杂 json 参数,如用户注册)
需求:用户注册时,前端传一个 json 格式的用户信息(包含姓名、年龄、手机号),后端接收这些参数,模拟 “保存用户”,然后返回 “注册成功” 的提示和保存后的用户信息(包含自动生成的用户 id)。
1. 写接口:用 “实体类” 接收请求体参数
在paramcontroller里加一个用户注册接口:
package com.example.firstspringbootproject.controller;
import com.example.firstspringbootproject.entity.product;
import com.example.firstspringbootproject.entity.user;
import org.springframework.web.bind.annotation.*;
import java.util.arraylist;
import java.util.list;
@restcontroller
public class paramcontroller {
// 模拟“用户数据库”:存注册后的用户
private list<user>userdb =new arraylist<>();
// 模拟自增id:每次注册新用户,id+1
private integer nextuserid = 3; // 之前已有id=1、2的用户,所以从3开始
/*
* 接口3:请求体传参——用户注册(接收json格式的用户信息)
* @postmapping:表示这个接口用post请求(前端传请求体一般用post,不用get)
* @requestbody:表示把请求体里的json数据,转换成user对象
*/
@postmapping("/user/register")
public string registeruser(@requestbody user user) {
// 1. 给新用户设置自增id(前端没传,后端自动生成)
user.setid(nextuserid);
nextuserid++; // 下次注册id+1
// 2. 模拟“保存用户”:把用户添加到“用户数据库”
userdb.add(user);
// 3. 返回注册成功的提示(包含用户信息)
return "注册成功!你的用户信息:" +
"id=" + user.getid() +
",姓名=" + user.getname() +
",年龄=" + user.getage() +
",手机号=" + user.getphone();
}
}
2. 关键说明(重点看这 2 个注解)
@postmapping:接收前端的 post 请求(get 请求一般用来 “查询” 数据,post 请求用来 “提交” 数据,比如注册、提交订单,这是开发中的规范);@requestbody:把前端请求体里的 json 数据,自动转换成user实体类对象 —— 这里的关键是:json 里的字段名要和user类的属性名完全一致(比如 json 里的 “name” 对应 user 类的private string name),否则无法正确赋值。
3. 测试接口(必须用 apifox,浏览器没法传请求体)
测试步骤:
打开 apifox,点击左上角「+」新建快捷请求;
「method」选择「post」,「url」输入:http://localhost:8080/user/register;
点击「body」→ 选择「json」→ 右侧下拉框选择「json」,在输入框里写前端要传的 json 数据:
{
"name": "小李",
"age": 22,
"phone": "13700137000"
}
点击右上角「send」,查看返回结果:
- 「response body」里会显示:
注册成功!你的用户信息:id=3,姓名=小李,年龄=22,手机号=13700137000; - 状态码是 200,表示请求成功。
再测试一次:
再传一个 json:
{
"name": "小李",
"age": 21,
"phone": "13600136000"
}
返回结果:注册成功!你的用户信息:id=4,姓名=小张,年龄=21,手机号=13600136000,id 自动增长,正确!
六、常见问题:接收参数时的小坑和解决方案
1. 路径传参时,参数名和占位符不一致,导致接收不到值?
- 比如路径是
/user/{id},但注解写的是@pathvariable("userid"),这样就会匹配失败; - 解决方案:确保
@pathvariable括号里的名称,和路径里{}的名称完全一致(比如@pathvariable("id"))。
2. 问号传参时,前端传了参数,但后端接收的是 null?
原因 :前端传的参数名和后端@requestparam里的参数名不一致(比如前端传product_name,后端用name);
3. 请求体传参时,实体类属性值是 null?
原因 :json 里的字段名和实体类属性名不一致(比如 json 里是 “username”,实体类是 “name”);
七、总结:3 种传参方式怎么选
今天我们学完了接收前端参数的 3 种核心方式,最后用一张表帮你快速判断该用哪种:
| 传参方式 | 注解 / 方式 | 适用场景 | 示例 url/json |
|---|---|---|---|
| 路径传参 | @pathvariable | 单个、简单参数(如 id、编号) | http://localhost:8080/user/1 |
| 问号传参 | @requestparam | 多个可选参数(如搜索条件) | http://localhost:8080/product/search?name=手机&maxprice=3000 |
| 请求体传参 | @requestbody + 实体类 | 复杂、多字段参数(如注册、提交订单) | {"name":"小李","age":22,"phone":"13700137000"} |
到此这篇关于springboot接收前端参数的最常用的场景和具体案例的文章就介绍到这了,更多相关springboot接收前端参数内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论