目录

Spring Boot - 请求参数接收

笔记

一直没时间总结 Spring Controller 接收参数的多种方式,只记得常用的 GET、POST 接收,而一些 List、Map 参数的接收却经常忘记怎么接收,每次都只能百度,所以现在总结不同的接收请求参数方式。

2022-12-12 @Young Kbt

# 支持的请求模式

GET 方式:主要用于简单查询,使用注解:@GetMapping 或者 @RequestMapping(method = RequestMethod.GET)

POST 方式:主要用于复杂查询或数据添加,使用注解:@PostMapping 或者 @RequestMapping(method = RequestMethod.POST)

HEAD、PUT、PATCH、DELETE、OPTIONS、TRACE 等方式不常用。

# 说明

  • 项目端口为 8085,在本地运行,所以是 http://localhost:8085
  • 内容用到了 @Slf4j 日志输出,安装了 lombok 依赖即可使用
  • 推荐使用 @GetMapping 或者 @PostPostMapping 看起来明确的请求方式
  • @RequestParam 只能用于 URL 后面 ? 携带参数的链接,@RequestBody 只能用于 JSON 格式的链接
  • 标题有 通用,代表 GET 和 POST 请求使用方式都一样,所以 POST 请求内容不再描述
  • 其实通过 URL 后面 ? 携带参数的链接,POST 和 GET 都是获取方式通用,只是 POST 需要的是更安装的传输:RequestBody

# GET 请求

# 基本类型参数注入(通用)

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
    @GetMapping("/simpleGet")
    public void simpleGet(String name, String age) {
        log.info("接收的参数:{}, {}", name, age);
    }
}
1
2
3
4
5
6
7
8
9
10

请求连接:http://localhost:8085/test/simpleGet?name=kele&age=18

日志输入:

2022-12-12 21:55:24.535  INFO 18888 --- [nio-8085-exec-1] com.pxw.mit.controller.TestController    : 接收的参数:kele, 18
1

# 指定参数注入(通用)

如果前端传来的链接和参数名不一致时,则需要指定前端传来的参数,用到 @RequestParam 注解。

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @GetMapping("/appointGet")
    public void appointGet(@RequestParam("name1") String name, @RequestParam("age1") String age) {
        log.info("接收的参数:{}, {}", name, age);
    }
}
1
2
3
4
5
6
7
8
9
10

请求连接:http://localhost:8085/test/appointGet?name1=bingtang&age1=17

日志输出:

2022-12-12 22:01:03.398  INFO 4024 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数:bingtang, 17
1

# 占位符参数注入(通用)

@PathVariable 映射 URL 绑定的 占位符

通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中 URL 中的 {xxx}。

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @GetMapping("/pathVariableGet/{name}/{age}")
    public void pathVariableGet(@PathVariable String name, @PathVariable String age) {
        log.info("接收的参数:{}, {}", name, age);
    }
}
1
2
3
4
5
6
7
8
9
10

请求连接:http://localhost:8085/test/pathVariableGet/xueli/18

日志输出:

2022-12-12 22:08:31.110  INFO 11260 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数:xueli, 18
1

可以看到和 ? 方式比读起来更加舒服。

如果参数名称和地址占位符不一致,则需要利用 @PathVariable 指定。

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @GetMapping("/pathVariableGet/{name1}/{age1}")
    public void pathVariableGet(@PathVariable("name1") String name, @PathVariable("age1") String age) {
        log.info("接收的参数:{}, {}", name, age);
    }
    
}
1
2
3
4
5
6
7
8
9
10
11

请求连接:http://localhost:8085/test/pathVariableGet/xueli/18

日志输出:

2022-12-12 22:10:53.839  INFO 16900 --- [nio-8085-exec-3] com.pxw.mit.controller.TestController    : 接收的参数:xueli, 18
1

# 实体类参数注入(通用)

简单

可以自定义一个实体类,属性和前端传来的参数名一致,且有 setter 和 getter 方法即可自动注入。

public class User {
    
    private String name;
    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

测试

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
    @GetMapping("/beanGet")
    public void beanGet(User user) {
        log.info("接收的参数:{}, {}", user.getName(), user.getAge());
    }
}
1
2
3
4
5
6
7
8
9
10

请求链接:http://localhost:8085/test/beanGet?name=xueli&age=17

日志输出:

2022-12-12 22:20:29.293  INFO 4404 --- [nio-8085-exec-3] com.pxw.mit.controller.TestController    : 接收的参数:xueli, 17
1

多个重复的实体类

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
   @GetMapping("/beanGet")
    public void beanGet(User user1, User user2) {
        log.info("接收的参数1:{}, {}", user1.getName(), user1.getAge());
        log.info("接收的参数2:{}, {}", user2.getName(), user2.getAge());
    }
}
1
2
3
4
5
6
7
8
9
10
11

请求链接:http://localhost:8085/test/beanGet?name=xueli&age=17

日志输出:

2022-12-12 22:24:17.323  INFO 1824 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数1:xueli, 17
2022-12-12 22:24:17.324  INFO 1824 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数2:xueli, 17
1
2

可以看出,只要前端传来的参数名和实体类的属性名匹配,则全部注入进去。

多个不相同的实体类

其实从上面也可以看出,只要属性名匹配,则不管多少个实体类,都注入。

准备一个新的类 Other

public class Other {
    
    private String email;
    private String phone;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

测试

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
   @GetMapping("/beanGet")
    public void beanGet(User user, Other other) {
        log.info("接收的参数1:{}, {}", user.getName(), user.getAge());
        log.info("接收的参数2:{}, {}", other.getEmail(), other.getPhone());
    }
}
1
2
3
4
5
6
7
8
9
10
11

请求链接:http://localhost:8085/test/beanGet?name=xueli&age=17

日志输出:

2022-12-12 22:29:41.427  INFO 17612 --- [nio-8085-exec-7] com.pxw.mit.controller.TestController    : 接收的参数1:xueli, 17
2022-12-12 22:29:41.427  INFO 17612 --- [nio-8085-exec-7] com.pxw.mit.controller.TestController    : 接收的参数22456@qq.com, 13377456541
1
2

这里就不「部分相同的实体类」了,如果参数存在 实体类和基本类型参数,只要参数名匹配,都全部注入。

总结:GET 请求中,只要实体类的属性名或者基本类型参数名能匹配,则不管多少个实体类,都注入值。

# 实体类 List 集合

虽然是 GET 请求,但是一旦用到 List 集合,就需要满足两个条件:

  • 使用 @RequestBody
  • 参数必须是 JSON 格式(POST 请求的传参方式),不能是在 URL ? 后面
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
    @GetMapping("/listBeanGet")
    public void listBeanGet(@RequestBody List<User> user) {
        log.info("接收的参数:{}", user);
    }
}
1
2
3
4
5
6
7
8
9
10

请求链接:http://localhost:8085/test/listBeanGet

JSON 参数:

[
    {
        "name": "kele",
        "age": "18"
    },
    {
        "name": "bingtang",
        "age": "17"
    }
]
1
2
3
4
5
6
7
8
9
10

如图:

image-20221213000750645

日志输出:

2022-12-12 22:41:32.873  INFO 3452 --- [nio-8085-exec-1] com.pxw.mit.controller.TestController    : 接收的参数:[User(name=kele, age=18), User(name=bingtang, age=17)]
1

如果多个 List 集合的参数怎么办?

如:

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
    @GetMapping("/listBeanGet")
    public void listBeanGet(@RequestBody List<User> user, List<Other> othe) {
        log.info("接收的参数:{}", user);
    }
}
1
2
3
4
5
6
7
8
9
10

这样是 不行的,出现异常的,目前我暂未发现如何注入两种对象集合类型。

注意:@RequestBody 在一个方法里只能用一次,因为 @RequestBody 修饰的参数一旦注入了数据,那么请求流将关闭,这样后面 @RequestBody 修饰的其他参数无法获取数据,并且抛出异常。

# 基本类型 List 集合(通用)

  • 需要使用 @RequestParam 修饰才能接收 List 集合
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    

    @GetMapping("/listSimpleGet")
    public void listSimpleGet(@RequestParam List<String>  name) {
        log.info("接收的参数:{}", name);
    }
}
1
2
3
4
5
6
7
8
9
10
11

请求连接:http://localhost:8085/test/listSimpleGet?name=kele&name=xueli

日志输出:

2022-12-12 22:52:24.627  INFO 10784 --- [nio-8085-exec-4] com.pxw.mit.controller.TestController    : 接收的参数:[kele, xueli]
1

name 和前端的传参名一致。

参数名和前端传来的不一致

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @GetMapping("/listSimpleGet")
    public void listSimpleGet(@RequestParam("name1") List<String> name) {
        log.info("接收的参数:{}", name);
    }
}
1
2
3
4
5
6
7
8
9
10

请求连接:http://localhost:8085/test/listSimpleGet?name1=kele&name1=xueli

日志输出:

2022-12-12 22:54:33.958  INFO 27768 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数:[kele, xueli]
1

多个 List 参数

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
    @GetMapping("/listSimpleGet")
    public void listSimpleGet(@RequestParam List<String> name, @RequestParam List<String> age) {
        log.info("接收的参数1:{}", name);
        log.info("接收的参数2:{}", age);
    }
}
1
2
3
4
5
6
7
8
9
10
11

请求连接:http://localhost:8085/test/listSimpleGet?name=kele&age=18&name=xueli&age=17

日志输出:

2022-12-12 22:57:51.469  INFO 9972 --- [nio-8085-exec-4] com.pxw.mit.controller.TestController    : 接收的参数1[kele, xueli]
2022-12-12 22:57:51.470  INFO 9972 --- [nio-8085-exec-4] com.pxw.mit.controller.TestController    : 接收的参数2[18, 17]
1
2

同理,只要前端传入的参数名和后端接收的一致,则可以注入。

# 基本类型 Map 类型(通用)

Map 参数需要用 @RequestParam 修饰才能接收。

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @GetMapping("/mapSimpleGet")
    public void mapSimpleGet(@RequestParam Map<String, String> map) {
        log.info("接收的参数:{}", map);
    }
}
1
2
3
4
5
6
7
8
9
10

请求链接:http://localhost:8085/test/mapSimpleGet?name=kele&age=18

日志输出:

2022-12-12 23:03:52.587  INFO 31556 --- [nio-8085-exec-1] com.pxw.mit.controller.TestController    : 接收的参数:{name=kele, age=18}
1

多个 Map

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
    @GetMapping("/mapSimpleGet")
    public void mapSimpleGet(@RequestParam Map<String, String> map1, @RequestParam Map<String, String> map2) {
        log.info("接收的参数1:{}", map1);
        log.info("接收的参数2:{}", map2);
    }
}
1
2
3
4
5
6
7
8
9
10
11

请求链接:http://localhost:8085/test/mapSimpleGet?name=kele&age=18

日志输出:

2022-12-12 23:05:12.785  INFO 2488 --- [nio-8085-exec-3] com.pxw.mit.controller.TestController    : 接收的参数1{name=kele, age=18}
2022-12-12 23:05:12.785  INFO 2488 --- [nio-8085-exec-3] com.pxw.mit.controller.TestController    : 接收的参数2{name=kele, age=18}
1
2

无论多少个,依然全部注入。

注意:参数的 Map<String, String> 泛型可以随便填,如 Map<String, Integer>Map<String, User>,Spring 不会管你的 Map 泛型,它默认都是 Map<String, String> 注入。

# 基本类型数组(通用)

直接接收即可

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    
    @GetMapping("/arraySimpleGet")
    public void arraySimpleGet(String[] name) {
        log.info("接收的参数:{}, {}", name[0], name[1]);
    }
}
1
2
3
4
5
6
7
8
9
10

请求链接:http://localhost:8085/test/arraySimpleGet?name=kele&name=xueli

日志输出:

2022-12-12 23:14:44.518  INFO 22476 --- [nio-8085-exec-3] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
2022-12-12 23:14:44.534  INFO 22476 --- [nio-8085-exec-3] com.pxw.mit.controller.TestController    : 接收的参数:kele, xueli
1
2

前端传来的参数名和后端参数名不一样

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @GetMapping("/arraySimpleGet")
    public void arraySimpleGet(@RequestParam("name1") String[] name) {
        log.info("接收的参数:{}, {}", name[0], name[1]);
    }
}
1
2
3
4
5
6
7
8
9
10

请求链接:http://localhost:8085/test/arraySimpleGet?name=kele&name=xueli

日志输出:

2022-12-12 23:15:54.526  INFO 17492 --- [nio-8085-exec-1] com.pxw.mit.controller.TestController    : 接收的参数:kele, xueli
1

多个数组参数

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @GetMapping("/arraySimpleGet")
    public void arraySimpleGet(String[] name, String[] age) {
        log.info("接收的参数1:{}, {}", name[0], name[1]);
        log.info("接收的参数2:{}, {}", age[0], age[1]);
    }
}
1
2
3
4
5
6
7
8
9
10
11

请求链接:http://localhost:8085/test/arraySimpleGet?name=kele&age=18&name=xueli&age=17

日志输出:

2022-12-12 23:17:37.961  INFO 25276 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数1:kele, xueli
2022-12-12 23:17:37.961  INFO 25276 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数218, 17
1
2

# POST 请求 - JSON

为了简洁,POST 请求的代码块直接写方法,类始终是上面的 TestController 类。

注意此时的请求链接是 POST 请求,且 @RequestBody 只接收 JSON 参数。

GET 请求里,除了 实体类 List 集合 外,其他的方式 POST 通用(URL 后面 ? 携带参数)。

说明:一个方法里 @RequestBody 只能用一次,也就是说接收的 JSON 只能有一个参数接收,其他参数只能从其他方式如 URL ? 后面传过来

因为 @RequestBody 执行一次后,就关闭请求流,导致其他 @RequestBody 修饰的参数无法获取 JSON,然后抛出异常。

# 基本类型参数注入

@PostMapping("/simplePost")
public void simplePost(@RequestBody String str) {
    log.info("接收的参数:{}", str);
}
1
2
3
4

请求链接:http://localhost:8085/test/simplePost

JSON 参数:

{
    "name": "kele",
    "age": "18"
}
1
2
3
4

日志输出:

2022-12-12 23:34:07.042  INFO 26364 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数:{
    "name": "kele",
    "age": "18"
}
1
2
3
4

这是个字符串。

# 实体类参数注入

@PostMapping("/beanPost")
public void beanPost(@RequestBody User user) {
    log.info("接收的参数:{}, {}", user.getName(), user.getAge());
}
1
2
3
4

请求链接:http://localhost:8085/test/beanPost

JSON 参数:

{
    "name": "kele",
    "age": "18"
}
1
2
3
4

输出日志:

2022-12-12 23:36:35.842  INFO 25052 --- [nio-8085-exec-1] com.pxw.mit.controller.TestController    : 接收的参数1:kele, 18
1

如果接收多个实体类,就将这些实体类封装到一个更大的实体类。如果还有其他实体类,那就继续封装成更更大的实体类 ......(没办法)

如果接收基础类型的参数,如 String name,则通过 URL ? 后携带 name 过来即可。也就是说,这种方式不限制多次接收。

# 实体类 List 集合

@PostMapping("/listBeanPost")
public void listBeanPost(@RequestBody List<User> user) {
    log.info("接收的参数:{}", user);
}
1
2
3
4

请求链接:http://localhost:8085/test/listBeanPost

JSON 参数:

[
    {
        "name": "kele",
        "age": "18"
    },
    {
        "name": "xueli",
        "age": "17"
    }
]
1
2
3
4
5
6
7
8
9
10

日志输出:

2022-12-12 23:43:17.329  INFO 22628 --- [nio-8085-exec-2] com.pxw.mit.controller.TestController    : 接收的参数:[User(name=kele, age=18), User(name=xueli, age=17)]
1

# POST 请求 - form

x-www-form-unlencoded 请求和 GET 请求的方式基本类似,这里仅仅说明一些注意细节,具体方式情况上面的 GET 请求

如果使用 x-www-form-unlencoded 传参,则注意以下几点:

  • 实体类、实体类集合作为参数,只能接收 JSON 格式的参数,无法接收 x-www-form-unlencoded
  • 如果是其他类型(非实体类)的参数,则需要在每个参数前面加上 @RequestParam 即可,包括 List、Map、数组
  • 参数名要和前端传来的保持一致,如果不想保持,则用 @RequestParam("xxx") 指定前端的参数名,xxx 就是前端的参数名

如:

@PostMapping("/listSimplePost")
public void listSimplePost(@RequestParam List<String> name) {
    log.info("接收的参数:{}", name);
}

@PostMapping("/mapSimplePost")
public void mapSimplePost(@RequestParam Map<String, String> map) {
    log.info("接收的参数:{}", map);
}

@PostMapping("/arraySimplePost")
public void arraySimplePost(String[] name, String[] age) {
    log.info("接收的参数1:{}, {}", name[0], name[1]);
    log.info("接收的参数2:{}, {}", age[0], age[1]);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

请求链接:

  • http://localhost:8085/test/listSimplePost
  • http://localhost:8085/test/mapSimplePost
  • http://localhost:8085/test/arraySimplePost

请求的参数

image-20221213000346342

日志输出:

2022-12-13 00:04:59.154  INFO 16928 --- [io-8085-exec-10] com.pxw.mit.controller.TestController    : 接收的参数:[kele, xueli]
    
2022-12-13 00:04:17.087  INFO 16928 --- [nio-8085-exec-8] com.pxw.mit.controller.TestController    : 接收的参数:{name=kele, age=18}

2022-12-13 00:04:20.289  INFO 16928 --- [nio-8085-exec-9] com.pxw.mit.controller.TestController    : 接收的参数1:kele, xueli
2022-12-13 00:04:20.289  INFO 16928 --- [nio-8085-exec-9] com.pxw.mit.controller.TestController    : 接收的参数218, 17
1
2
3
4
5
6

除实体类和 Map、List、数组外,其他和 GET 请求的方式一致。如果您不放心,则每个参数前都加 @RequestParam 即可。

# 结束语

后面如果遇到其他的接收方式,则会更新。

如果您有其他优雅的方式,或者您有其他补充或疑惑,可以在评论一起讨论。

更新时间: 2024/01/17, 05:48:13
最近更新
01
JVM调优
12-10
02
jenkins
12-10
03
Arthas
12-10
更多文章>