在客户端向服务端发起请求时,往往会携带各种相关的请求数据(比如在删除员工的时候需要携带员工的id),这些请求数据通过多种形式(如直接写在URL中的参数,请求体中的json数据等),在后端程序(controller层)需要将这些请求数据正确的接收并正确的封装使用。这些参数常见的有:简单参数、数组集合参数、日期参数、json参数、路径参数等,都需要用不同的方法进行获取。(以下演示代码,案例都基于SpringBoot框架)
简单参数的获取
原始方式
在原始的web程序中,获取请求参数,需要通过HttpServletRequest对象进行手动获取,假如说定义一个请求,请求参数有name和age,使用HttpServletRequest对象获取:
java
@RequestMapping("/simple")
public String getSimpleParameter(HttpServletRequest httpServletRequest) {
String name = httpServletRequest.getParameter("name");
// 通过HttpServletRequest对象获取的请求参数都是String类型的,需要手动进行类型转换
int age = Integer.parseInt(httpServletRequest.getParameter("age"));
System.out.println("姓名是: " + name + "年龄是: " + age);
return "hello " + name + age;
}
在客户端发起请求:
发现服务端通过原始方式,通过HTTPServletRequest对象手动获取参数,成功接收请求参数:
由此可以看见,获取简单参数还是比较简单的,但是既然都是SpringBoot项目了,那么还使用原始的方式未免有些过于"笨拙"了,可以通过SpringBoot框架的方法更加简单的获取简单请求参数。
框架提供的便捷方式
在SpringBoot框架中,想要接收请求携带的简单参数,只需要在controller方法中声明对应的形参即可接收到,但是需要特别提醒的是:形参名必须和请求参数名相同。 总结而言:通过SpringBoot框架接收请求中的简单参数,在方法声明中定义和请求中参数名相同的形参就可以接收参数。
java
@RequestMapping("/simple")
public String getSimpleParameter(String name, int age) {
System.out.println("姓名是: " + name + "年龄是: " + age);
return "hello " + name + age;
}
可以发现并没有通过冗杂的HttpServletRequest类手动获取请求参数,只需要在Controller的方法声明和请求参数同名的形参,SpringBoot就可以让方法中的形参去自动接收请求中的简单参数,这十分的方便。
使用post请求方法也可以正确的接收到参数:
叛逆期
上文已经提及,如果想要通过SpringBoot框架成功接收到请求参数,那么就必须保证接收的方法中的形参和请求参数同名,但是假如说"叛逆期"到了,我就使用不同名的形参接收,那么还会成功接收到吗?我们将形参改为username再次启动服务:
java
@RequestMapping("/simple")
public String getSimpleParameter(String username, int age) {
System.out.println("姓名是: " + username + "年龄是: " + age);
return "hello " + username + age;
}
发现若形参名和请求参数名字不同时,就无法接收到请求参数了,那么username这个形参自然也便是null了。但是参数不对应就一定无法接收成功吗》其实也未必,只是现在需要稍微麻烦一点,SpringBoot提供了@RequestParam注解,便于当方法形参名和请求参数名不匹配时,通过@RequestParam注解完成映射:通过注解中的name属性指定请求参数名即可 (注意:注解中的name属性必须和请求参数名完全一致了,否则真没办法接收了!)
java
@RequestMapping("/simple")
public String getSimpleParameter(@RequestParam(name="name") String username, int age) {
System.out.println("姓名是: " + username + "年龄是: " + age);
return "hello " + username + age;
}
此时,虽然函数中的形参名和请求参数名无法对应,但是通过@RequestParam注解指定这个形参应该对应的请求参数名,从而完成映射:
此时,通过@RequestParam指定了形参应该对应的请求参数,从而成功接收到了请求参数;但是仍然是不建议这么使用的:首先是因为这样的方法不是那么的规范,其次,只要设置了@RequestParam注解的参数就必须要传递,否则将会报警告:
java
2024-12-04T00:04:45.869+08:00 WARN 21552 ---
[JavaWeb06_Develop] [nio-8080-exec-5] .w.s.m.s.DefaultHandlerExceptionResolver :
Resolved [org.springframework.web.bind.MissingServletRequestParameterException:
Required request parameter 'name' for method parameter type String is not present]
这个警告的意思是必须的请求参数"name"不存在。这个原因就是@RequestParam注解中有个属性------required,这个属性默认为true,表示这个参数必须要传递,所以说如果我们不传递该参数,就会报警告。可以将其设置为false,这样即使不传递该参数程序也可以正常运行。
java
@RequestMapping("/simple")
public String getSimpleParameter(@RequestParam(name="name", required = false) String username, int age) {
System.out.println("姓名是: " + username + "年龄是: " + age);
return "hello " + username + age;
}
实体参数的获取
若只是传递几个请求参数,那么通过方法中的形参进行接收也罢了,但是假如有多个参数,再使用形参接收就有些冗杂了,而且接收到的参数使用起来也很不方便;对于这种情况,我们就可以定义简单的实体对象来进行接收:请求参数名和对象的属性名相同。
先定义实体类用于接收参数,实体类的属性必须和参数名相同:
java
package com.wzb.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private int age;
}
发现确实通过实体对象接收到了多个请求参数。
复杂实体对象
假如请求参数是一个复杂的实体对象,比如说User对象中有个属性Address,Address属性是一个对象,其中又有属性province和city,那么此时只需要保证请求参数名和形参对象属性名相同,然后按照对象的层次结构关系即可接收嵌套的pojo属性参数。
java
@RequestMapping("/complexPojo")
public String getComplexParameter(TestUser user) {
String name = user.getName();
int age = user.getAge();
Address address = user.getAddress();
System.out.println("姓名是: " + name + "年龄是: " + age + "地址是: " + address.getProvince() + " " + address.getCity());
System.out.println(user);
return "hello " + name + age + address;
}
请求路径,及其请求参数封装:
发现只要按照对象的层次机构关系,即可接收到嵌套的pojo属性: