参数分为 路径参数、查询参数、请求体参数。
路径参数
参数出现在path中,可以使用 @PathVariable 接收。
@RestController
@RequestMapping("/api/hello")
public class HelloController {
@GetMapping("/{name}")
public ApiResponse<String> hello(@PathVariable("name") String name) {
return ApiResponse.success("Hello World!" + name);
}
}
当占位符({name})和变量名称(String name)一致的时候,@PathVariable("name") 的 name 可以缺省,如下所示:
@GetMapping("/{name}")
public ApiResponse<String> hello(@PathVariable String name) {
return ApiResponse.success("Hello World!" + name);
}
如果占位符是多个单词组成,推荐使用蛇形命名方式,比如 @GetMapping("/{project_name}"),对应 @PathVariable("project_name") String projectName。
查询参数
查询参数指的是拼接在路径后面的键值对,可以使用 @RequestParam 接收。
@RestController
@RequestMapping("/api/hello")
public class HelloController {
@GetMapping
public ApiResponse<String> hello(@RequestParam("name") String name) {
return ApiResponse.success("Hello World!" + name);
}
}
当 /api/hello?name=jack 和变量名称一致的时候,@RequestParam("name")的 name 可以省略,如下所示:
@GetMapping
public ApiResponse<String> hello(@RequestParam String name) {
return ApiResponse.success("Hello World!" + name);
}
如果查询参数是多个单词组成,也是推荐使用蛇形命名,比如 /api/hello?project_name=jack,对应 @RequestParam("project_name") String projectName。
默认值
查询参数默认是必填的,可以设置成非必填,并添加默认值。
@GetMapping
public ApiResponse<String> hello(@RequestParam(value = "name", defaultValue = "World") String name) {
return ApiResponse.success("Hello World!" + name);
}
表示如果name参数没有指定,则使用默认值 World,这个时候name是选填的。
其实注解 RequestParam 里面还有个属性是 required,表示是否是必填的,默认是true。写了 defaultValue 就等于告诉 Spring:“这个参数是可选的,没传就用默认值。”,不需要(也不建议)再写 required=false
查询参数封装成对象
当有很多个查询参数,可以每个查询参数都用 @RequestParam 接收,也可以将这些查询参数封装成一个对象。
@Data
public class Param {
private String name;
private String age;
}
@GetMapping
public ApiResponse<String> hello(@ModelAttribute Param param) {
return ApiResponse.success("Hello World!" + param.getName() + " " + param.getAge());
}
其中 @ModelAttribute 可直接省略,加不加都一样。
使用postman请求验证:
但是如果参数是多个单词组成的,而我们的习惯又是参数是蛇形命名,变量是驼峰。这里就会面临一个问题,蛇形命名的参数和驼峰的变量对应不上,即使使用 @JsonProperty 注解也不行,因为 @JsonProperty 作用在请求体可以,但是作用于查询参数行不通。
这里可以使用 全参构造 + @ConstructorProperties 注解解决。
@Data
public class Param {
private String projectName;
private String age;
@ConstructorProperties({"project_name", "age"})
public Param(String projectName, String age) {
this.projectName = projectName;
this.age = age;
}
}
注意这里不要再定义无参构造,否则 spring 封装参数的时候优先走 无参构造 + setter,从而绕过 @ConstructorProperties 的字段映射关系。
这样的话,projectName才能正常接收到值:
请求体参数
任何HTTP方法都可以带查询参数,但是并不是所有的HTTP方法都推荐带请求体参数,比如GET或者DELETE请求方式就不推荐将参数放在请求体中,技术上是可以的,但是规范上不行,个别代理(nginx)会主动抛弃GET或者DELETE的请求体参数。
请求体参数可以使用 @RequestBody 接收。
@PostMapping
public ApiResponse<String> hello(@RequestBody Request request) {
return ApiResponse.success("Hello World!" + request.getName() + " " + request.getMyAge());
}
@Data
public class Request {
private String name;
@JsonProperty("my_age")
private String myAge;
}
请求体参数的字段值都是可选的,即使不传递也不会报错,如果不指定的话为 null 值。