目录
- 3. 请求
- 传递单个参数
- 传递多个参数
- 传递对象
- 后端参数重命名
- 传递数组
- 传递集合
3. 请求
请求就是要学习如何传参
- 传递单个参数
- 多个参数
- 对象
- 数组/集合……
传递单个参数
@RequestMapping("/m1")
public String m1(String name){
return "接收到的参数name:"+name;
}
底层逻辑:需要名称一样,从请求的参数中,获取参数名为name
值,并给name
赋值
传递多个参数
@RequestMapping("/m2")
public String m2(String name,Integer age){
return"接收到的参数name:"+name+",age:"+age;
}
这里顺序是无所谓的,先age
再name
也行,参数的顺序可以调换,上述情况不赋值就会是null
而已,但注意下面这种情况
使⽤基本类型来接收参数时, 参数必须传(除boolean类型), 否则会报500错误,类型不匹配时, 会报400错误.
@RequestMapping("/m3")
public String m3(String name,int age){
return"接收到的参数name:"+name+",age:"+age;
}
java.lang.IllegalStateException: Optional int parameter 'age' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.
这个是报错信息,简单说:没有办法把int类型的age
置为null
,建议我们用包装类
如果使用基本类型必须传值,不然就会报错
对于包装类型, 如果不传对应参数,Spring 接收到的数据则为null
所以企业开发中,对于参数可能为空的数据,建议使⽤包装类型,即Integer
这种类型
传递对象
如果参数⽐较多时, ⽅法声明就需要有很多形参. 并且后续每次新增⼀个参数, 也需要修改⽅法声明.
我们不妨把这些参数封装为⼀个对象。Spring MVC 也可以⾃动实现对象参数的赋值
Person
类
public class Person {
Integer id;
String name;
Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
@RequestMapping("/m4")
public String m4(Person person){
return "接收到的参数person:"+person.toString();
}
Spring 会根据参数名称⾃动绑定到对象的各个属性上, 如果某个属性未传递, 则赋值为null(基本类型则赋值为默认初识值, ⽐如int类型的属性, 会被赋值为0)
开发中,接口的参数通常定义为对象,方便扩展
后端参数重命名
某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不⼀致,⽐如前端传递了⼀个 time
给后端,⽽后端是使⽤ createtime
字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使⽤ @RequestParam
来重命名前后端的参数值.
后端对前端传来的参数名不是很满意,就自己修改了
通过注解,@RequestParam
重命名,通过注解重命名了,就必须用注解里改的参数名了
@RequestMapping("/m5")
public String m5(@RequestParam("name") String username){
return "接收到的参数name:"+username;
}
这里是把前端传来的username
改为name
了,注意不要搞反了
Required request parameter 'name' for method parameter type String is not present
这个是报错信息,说name
是个必传参数,如果不传就会报错了
@RequestMapping("/m5")
public String m5(@RequestParam(value = "name",required = false) String username){
return "接收到的参数name:"+username;
}
这样就不会是必传的了
虽然也无法传参成功,但name
不是必传的了,也就不会报错了
结论:
- 使⽤
@RequestParam
进⾏参数重命名时, 请求参数只能和@RequestParam
声明的名称⼀致, 才能进⾏参数绑定和赋值. - 使⽤
@RequestParam
进⾏参数重命名时, 参数就变成了必传参数.
传递数组
Spring MVC 可以⾃动绑定数组参数的赋值
@RequestMapping("/m6")
public String m6(String[] arrayParam){
return "接收到的参数arrayParam:"+ Arrays.toString(arrayParam);
}
数组参数:请求参数名与形参数组名称相同且请求参数为多个, 后端定义数组类型形参即可接收参数
http://127.0.0.1:8080/param/m6?arrayParam=zhangsan&arrayParam=lisi&arrayParam=wangwu
或者使⽤
http://127.0.0.1:8080/param/m6?arrayParam=zhangsan%2clisi%2cwangwu
或者使⽤
http://127.0.0.1:8080/param/m6?arrayParam=zhangsan,lisi,wangwu
传递集合
如果直接传递
@RequestMapping("/m7")
public String m7(List<String> listParam){
return "接收到的参数listParam:"+ listParam+",长度:"+listParam.size();
}
5开头的通常指服务器发生错误
4开头的通常指客户端发生错误
如果看到5开头的错误,第一反应看后端日志
java.lang.IllegalStateException: No primary or single unique constructor found for interface java.util.List
大概意思是:把这个
listParam
封装成数组了
集合参数:和数组类似, 同⼀个请求参数名有为多个, 且需要使⽤ @RequestParam
绑定参数关系
默认情况下,请求中参数名相同的多个值,是封装到数组. 如果要封装到集合,要使⽤
@RequestParam
绑定参数关系
@RequestMapping("/m7")
public String m7(@RequestParam List<String> listParam){
return "接收到的参数listParam:"+ listParam+",长度:"+listParam.size();
}
请求⽅式和数组类似,浏览器传参:
⽅式⼀: http://127.0.0.1:8080/param/m7?listParam=zhangsan&listParam=lisi&listParam=wangwu
⽅式⼆: http://127.0.0.1:8080/param/m7?listParam=zhangsan%2clisi%2cwangwu
%2c 是逗号的转义编码, 解码后的url为:
http://127.0.0.1:8080/param/m7?listParam=zhangsan,lisi,wangwu
状态码是后端自定义的吗?
http状态码不是后端定义的
2XX:成功
3XX:重定向
4XX:客户端错误
5XX:服务器错误业务状态码:http响应成功的情况下,业务的相应结果分为不同的状态
比如用户登录:
- 密码正确 => 200
- 密码错误 => -1
这个状态码是后端自定义的
以上的传递方式,开发基本不使用