获取键值对格式的请求参数
注入request对象获取
前端控制器接收请求然后调用匹配请求路径的控制器方法, 如果发现控制器方法的形参类型是HttpServletRequest
类型就自动给该形参赋值
- 当控制器方法的形参类型是
HttpServletRequest,HttpServletResponse,HttpSession
任意一种类型时,前端控制器都会为该形参赋值
<a th:href="@{/testServletAPI(username='admin',password=123456)}">测试使用servletAPI获取请求参数</a><br>
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request){
// 这个request是由前端控制器注入的
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username:"+username+",password:"+password);
return "success";
}
声明同名形参获取
前端控制器接收请求然后调用匹配请求路径的控制器方法,如果发现控制器方法的形参名和某个请求参数name相同
就自动给该形参赋对应的value值
- 如果请求的请求参数中没有和控制器方法形参名相同的name此时形参的值是默认值
<a th:href="@{/testParam(username='admin',password=123456)}">测试使用控制器的形参获取请求参数</a><br>
@RequestMapping("/testParam")
public String testParam(String username, String password){
// username:admin,password:123456
System.out.println("username:"+username+",password:"+password);
return "success";
}
如果发现控制器方法的形参名和请求的多个请求参数name同名
,此时根据控制器方法形参的类型决定如何存储请求路径中这些同名的请求参数
- 若使用
字符串类型的形参
: 控制器方法形参的值为每个同名请求参数name的vlaue值中间使用逗号拼接的字符串如(a,b,c)
- 若使用
字符串数组类型的形参
: 控制器方法形参数组的每一个元素对应每个同名请求参数name的vlaue值如[a,b,c]
<!--表单发送的是GET请求表示请求参数以name=value的格式存储到浏览器的地址栏中-->
<!--表单发送的是POST请求表示请求参数以name=value的格式存储到请求体-->
<form th:action="@{/testParam}" method="get">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<!--请求参数name相同-->
爱好:<input type="checkbox" name="hobby" value="a">a
<input type="checkbox" name="hobby" value="b">b
<input type="checkbox" name="hobby" value="c">c<br>
<input type="submit" value="测试使用控制器的形参获取请求参数">
</form>
@RequestMapping("/testParam")
public String testParam(String username, String password,String[] hobby)
System.out.println("username:"+username+",password:"+password+",hobby:"+ Arrays.toString(hobby));
return "success";
}
数组能接收多个值那么集合
也可以接收,但是需要使用@RequestParam
注解声明,这样才会把请求参数作为元素放入List集合中
- SpringMVC默认会把
List集合
看做是一个POJO对象来处理,底层需要创建对象并把请求参数的数据封装到该对象中,但是List是一个接口无法创建对象所以报错
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List hobbies) {
// 集合参数传递user —> [sing, jump, rap, basketball]
System.out.println("集合参数传递user --> " + hobbies);
return "{'module':'list param'}";
}
@RequestParam注解
如果控制器方法形参名和请求参数名不一致时可以使用@RequestParam注解
指定url或表单
携带的请求参数name的value值要赋值给哪一个形参
- 由于Tomcat对于表单的POST请求做了特殊处理,使得可以通request.getParamter()将值取出,即可以控制器方法参数上使用
@RequestParam
注解将数据绑定在参数上 - 如果没有设置defaultValue属性且required属性是默认值,此时要求指定的请求参数name必须携带否则报400错误
在/book/{user}?user=admin
中@RequestParam("user") 和 @PathVariable("user")
获取请求参数的区别
@PathVariable("user")
获取的是请求路径上占位符的值@RequestParam("user")
获取的是请求路径/请求体中?
后面的请求参数name对应的value值
属性名 | 作用 |
---|---|
value | 指定某个请求参数的name为所标识的控制器方法的该形参赋值 |
required | 默认值为true表示表示必须携带该请求参数, false表示非必须携带请求参数, 如果没有携带则注解所标识的方法形参的值为null |
defaultValue | 不管required属性值为true或false,当没有指定的请求参数name或请求参数name的值为""时使用默认值为控制器方法的形参赋值 |
@RequestMapping("/testParam")
public String testParam(@RequestParam(value = "user_name", required = false, defaultValue = "hello") String username)
System.out.println("username:"+username);
return "success";
}
@RequestHeader注解
@RequestHeade注解指定请求的某个请求头参数name的value值要赋值给哪一个形参
,请求头参数不能直接在控制器方法上声明同名形参获取
- @RequestHeade注解的value、required、defaultValue属性和@RequestParam注解用法一样
@RequestMapping("/testParam")
public String testParam(@RequestHeader(value = "Host", required = true, defaultValue = "haha" ) String host)
System.out.println("host:"+host);
return "success";
}
@CookieValue注解
具体session和cookie的使用参考文章
传统方式获取某个Cookie对象的value值需要先获取所有Cookie对象,根据name确定对应的Cookie对象然后获取它的value值
Cookie[] cookies =request.getCookies();
for(Cookie c:cookies){
if(c.getName().equals("JSESSIONID")){
String cv = c.getValue();
}
@CookieValue注解指定请求的某个name的Cookie对象的value值要赋值给哪一个形参
,不能直接在控制器方法上声明同名形参获取
- @CookieValue注解的value、required、defaultValue属性和@RequestParam注解用法一样
- 第一次发请求时需要先获取session对象,此时服务器端会创建一个session对象并返回其对应的
Cookie对象(JSESSIONID=xxx)
给浏览器 - Cookie默认关联的路径是当前路径的上级路径及其子路径,所以第二次只要发起符合要求的请求路径就会携带这个Cookie对象
@RequestMapping("/testsession")
public String testParam(HttpServletRequest request){
// 获取session,服务端创建完一个session对象会返回其对应的Cookie对象(JSESSIONID=xxx)到浏览器
// 响应的Cookie对象关联的路径/SpringMvc及其子路径
HttpSession httpsession = request.getSession();
}
@RequestMapping("/testParam")
public String testParam(@CookieValue("JSESSIONID") String JSESSIONID){
System.out.println("JSESSIONID:"+JSESSIONID);
return "success";
}
声明实体类的同名属性获取
如果请求的请求参数name有多个时,声明多个同名形参数据比较繁琐,此时可以将形参声明为实体类然后在实体类声明同名的属性接收请求参数name的value值
- 将实体类的属性名当作name从请求的请求参数中获取name对应的value值 , 找到则为该属性赋值 ,没有找到属性就是默认值
- 底层利用的是反射机制创建实体类对象,所以要求实体类必须提供无参构造方法
应用场景: 当请求的请求参数name对应的是数据库中表的字段值,我们可以直接将其封装进一个实体类对象中,然后调用Dao层的方法将对象存入数据库
@Date
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String sex;
private String email;
// 底层使用反射创建对象必须提供无参构造
public User() {
}
}
<form th:action="@{/testpojo}" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
性别:<input type="radio" name="sex" value="男">男<input type="radio" name="sex" value="女">女<br>
年龄:<input type="text" name="age"><br>
邮箱:<input type="text" name="email"><br>
<input type="submit">
</form>
@RequestMapping("/testpojo")
public String testPOJO(User user){
// User{id=null, username='张三', password='123', age=23, sex='男', email='123@qq.com'}
System.out.println(user);
return "success";
}
嵌套POJO类型
嵌套POJO参数
: 请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
- 发送请求和参数:
localhost:8080/user/pojoParam?name=Helsing&age=1024&address.province=Beijing&address.city=Beijing
public class User {
private String name;
private int age;
private Address address;
//get和set方法以及toString()方法
}
public class Address {
private String province;
private String city;
//get和set方法以及toString()方法
}
后台编写控制器方法接收参数
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
// POJO参数传递user —> User{name=’Helsing’, age=1024, address=Address{province=’Beijing’, city=’Beijing’}}
System.out.println("POJO参数传递user --> " + user);
return "{'module':'pojo param'}";
}
@DateTimeFormat日期类型
日期类型比较特殊,因为对于日期的格式有N多中输入方式,比如2088-08-18,2088/08/18,08/18/2088
等
使用PostMan发送请求:localhost:8080/user/dateParam?date=2077/12/21
,编写方法接收日期数据
@RequestMapping("/dateParam")
@ResponseBody
public String dateParam(Date date) {
// Tue Dec 21 00:00:00 CST 2077
System.out.println("参数传递date --> " + date);
return "{'module':'date param'}";
}
新增一个日期格式,发送请求localhost:8080/user/dateParam?date1=2077/12/21&date2=1997-02-13
,发送请求和数据后页面会报400错误
- SpringMVC
默认支持的字符串转日期
的格式为yyyy/MM/dd
,如果传递的不符合SpringMVC的默认格式就无法进行格式转换
@RequestMapping("/dateParam")
@ResponseBody
public String dateParam(Date date1,Date date2) {
// 报MethodArgumentTypeMismatchException,方法的参数类型不匹配错误,即无法将String类型转化为Date类型
System.out.println("参数传递date1 --> " + date1);
System.out.println("参数传递date2 --> " + date2);
return "{'module':'date param'}";
}
@DateTimeFormat
注解的pattern
属性指定接收日期的格式并且可以携带具体的时间,发送请求参数date1=1997-02-13&date2=2022/09/09 16:34:07
@RequestMapping("/dateParam")
@ResponseBody
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern ="yyyy/MM/dd HH:mm:ss") Date date2) {
System.out.println("参数传递date2 --> " + date2);
System.out.println("参数传递date3 --> " + date3);
return "{'module':'date para m'}";
}
类型转换原理
前端传递字符串后端可以使用日期Date接收, 前端传递JSON数据后端可以使用对象接收, 前端传递字符串后端可以使用Integer接收
- 后台需要的数据类型有很多种,但是前端只能传递字符串或者JSON数据,所以在数据的传递过程中存在很多类型的转换
SpringMVC中提供了org.springframework.core.convert.converter
类型转换接口,它的不同实现类用来完成不同数据类型之间的转换
HttpMessageConverter
接口负责实现对象与JSON之间的转换工作- 对于没有自动开启的类型转换,需要在SpringMVC的配置类添加
@EnableWebMvc
注解开启MVC注解驱动,表示根据类型匹配对应的类型转换器
/**
* S: the source type
* T: the target type
*/
@FunctionalInterface
public interface Converter<S, T> {
@Nullable
//该方法就是将从页面上接收的数据(S)转换成我们想要的数据类型(T)返回
T convert(S source);
}