普通的数组 {#普通的数组}
定义一个简单的 Controller,它接收一个 String[]
类型的数组参数,如下:
@RestController
@RequestMapping("/demo")
public class DemoController {
@GetMapping
public Object demo (@RequestParam("hobby") String[] hobby) {
return hobby;
}
}
Spring Boot 可以直接把以逗号分割的参数封装为集合、数组,例如:
$ curl "localhost:8080/demo?hobby=chang,tiao,rap"
["chang","tiao","rap"]
其他框架、程序不一定会根据逗号进行分割。更优雅的方式,也是通用的方式应该是多次声明同名参数,例如:
$ curl "localhost:8080/demo?hobby=chang&hobby=tiao&hobby=rap"
["chang","tiao","rap"]
数组也可以替换为 Collection
接口,Spring 都会正确地处理。特别是在一些需要对数组参数去重的场景,推荐使用 Set
作为参数,如下:
@GetMapping
public Object demo (@RequestParam("hobby") Set<String> hobby) {
return hobby;
}
发起请求,这一次 rap
值重复传递了 3 次:
$ "localhost:8080/demo?hobby=chang&hobby=tiao&hobby=rap&hobby=rap&hobby=rap"
["chang","tiao","rap"]
得益于 Set
自带去重的特性,所以最终 hobby
集合中重复的 rap
值,只保留了一个。
使用
Set
作为参数的时候,默认使用的实现是java.util.LinkedHashSet
,目的是为了保证集合中的参数顺序和传递的顺序一样。
Spring 还会自动地把传递的字符串参数,转换为 Controller 方法声明的类型。
如,定义 Integer
类型的数组、集合:
@GetMapping
public Object demo (@RequestParam("val") Set<Integer> val) { // Set<Integer> 类型
return val;
}
发起请求,传递数值类型的字符串参数:
$ curl "localhost:8080/demo?val=1&val=2&val=3"
[1,2,3]
如果不能成功地转换,则会抛出异常。如下,最后一个参数传递了一个
NaN
字符串:$ curl "localhost:8080/demo?val=1&val=2&val=NaN" {"timestamp":"2023-09-22T09:07:48.592+00:00","status":400,"error":"Bad Request","path":"/demo"}
服务端异常消息如下:
Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String[]' to required type 'java.util.Set'; For input string: "NaN"]
甚至可以自动转换 LocalDate
类型:
@GetMapping
public Object demo (@RequestParam("times") Set<LocalDate> times) {
return times;
}
发起请求,传递日期格式的字符串参数:
curl "localhost:8080/demo?times=2023-09-22×=2023-09-23×=2023-09-24"
["2023-09-22","2023-09-23","2023-09-24"]
至于其他各种类型的参数,你都可以试一试!
对象中的普通数组 {#对象中的普通数组}
先定义一个简单的 User
对象,它有一个 String[]
类型的数组属性 :
public class User {
private Integer id;
private String name;
private String[] hobby; // 数组类型的参数
// 忽略 get、set 方法
}
修改 Controller,接收一个 User
类型的参数:
注意: 请求方式改为了 @PostMapping
,并且移除了 @RequestParam
注解。
@PostMapping
public Object demo (User user) {
return user;
}
为了更加直观的感受,这次使用 Postman 发起请求,对于数组类型的 hobby
参数,我们使用了逗号分割多个值:
也可以通过中括号 []
, 多次声明 hobby[]
来传递数组参数:
甚至可以在中括号中指定参数在数组中的索引,也就是下标。如下,我们把 rap
值放在了最前面,把 chang
值放在了最后面:
对象中的对象数组 {#对象中的对象数组}
修改 User
对象,它的 hobby
属性不再是一个普通的字符串数组。而是一个 Hobby
对象数组。
Hobby
对象以内部类形式定义,它有 2 个属性,如下:
public class User {
public static class Hobby {
private String id;
private String title;
}
private Integer id;
private String name;
private Hobby[] hobby; // Hobby 类型的数组属性
}
Controller 不需要改变。
由于数组参数 hobby
的元素类型是一个对象,对象有多个属性,因此需要在参数中指定其属性名称和值: