springboot学习第2期 - 参数接收

184 阅读3分钟

参数分为 路径参数、查询参数、请求体参数。

路径参数

参数出现在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 值。