常用参数注解使用
# 210.常用参数注解使用
一般来说,我们都是要从前端获取参数的,SpringBoot 提供了很多的方式
# 前言
大致可以分为如下 4 种方式:
注解,例如
@PathVariable
路径变量@RequestHeader
获取请求头@RequestParam
获取请求参数(指问号后的参数,url?a = 1&b = 2)@CookieValue
获取 Cookie 值@RequestAttribute
获取 request 域属性@RequestBody
获取请求体 [POST]@MatrixVariable
矩阵变量@ModelAttribute
Servlet API:WebRequest,ServletRequest,HttpSession
复杂参数:Map,Model...
自定义对象参数:可以自动类型转换与格式化,级联封装
例如,在方法参数里使用注解 @RequestParam
,然后赋值给 name:
@GetMapping("/user")
public String getUser(@RequestParam("username") String name){
return "GET-张三";
}
2
3
4
可以在方法中传入 Session 对象,然后就可以在方法中操作 Session 了:
@GetMapping("/user")
public String getUser(HttpSession session){
return "GET-张三";
}
2
3
4
复杂对象:例如 Model,可以放一些数据进去,这样前端就能获取到数据;
自定义对象:例如传入一个 Person 对象,这样前端传的值就会封装到对象中,方便后续的使用。
以上内容其实在 SpringMVC 请求参数的绑定 (opens new window) 讲过一些,现在再来复习下。
# @PathVariable:路径变量
新建一个 Controller:
package com.peterjxl.boot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class ParameterTestController {
@GetMapping("/car/{id}/owner/{username}") //REST风格
public Map<String, Object> getCar(@PathVariable("id") Integer id,
@PathVariable("username") String name) {
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("username", name);
return map;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
通过@GetMapping 里的占位符,以及方法参数中的@PathVariable,我们能获取到前端传的 id 和 name;
除此之外,在@PathVariable 的源码中,还有个注释:
If the method parameter is Map <String, String> then the map is populated with all path variable names and values.
也就是说,如果方法参数中有 Map<String, String>
,那么就会将所有路径变量的值都放到该集合中。
我们来测试下;
@GetMapping("/car/{id}/owner/{username}") //REST风格
public Map<String, Object> getCar(@PathVariable("id") Integer id,
@PathVariable("username") String name,
@PathVariable Map<String, String> pv) {
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("username", name);
map.put("pv", pv);
return map;
}
2
3
4
5
6
7
8
9
10
新建 resources/haha/parameter.html:
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>测试常用参数注解</title>
</head>
<body>
<a href="car/3/owner/lisi">测试PathVariable</a>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
访问 localhost: 8888/parameter.html (opens new window),点击超链接,能看到正常返回数据:
# @RequestHeader:获取请求头
需要获取 HTTP 请求头信息,可以使用该注解;同理,我们看其源码,有这样的注释:
Supported for annotated handler methods in Spring MVC and Spring WebFlux.
If the method parameter is Map <String, String>, MultiValueMap <String, String>, or HttpHeaders then the map is populated with all header names and values.
也就是说,如果方法的参数中包含 Map,MultiValueMap,HttpHeaders 三种类型,那么就会将所有请求头都封装到该参数中。
写段代码来验证下,在 ParameterTestController
中添加方法:
@GetMapping("/testRequestHeader")
public Map<String, Object> testRequestHeader(@RequestHeader("User-Agent") String userAgent,
@RequestHeader Map<String, String> headerMap) {
Map<String, Object> map = new HashMap<>();
map.put("User-Agent", userAgent);
map.put("headerMap", headerMap);
return map;
}
2
3
4
5
6
7
8
例如:
@GetMapping("/testRequestHeader")
public Map<String, Object> testRequestHeader(@RequestHeader("User-Agent") String userAgent) {
Map<String, Object> map = new HashMap<>();
map.put("User-Agent", userAgent);
return map;
}
2
3
4
5
6
修改 parameter.html:
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>测试常用参数注解</title>
</head>
<body>
<li><a href="/car/3/owner/lisi">测试PathVariable</a></li>
<li><a href="/testRequestHeader">测试RequestHeader</a></li>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
重启项目,访问 localhost: 8888/parameter.html,点击超链接,能看到正常获取了请求头信息:
# @RequestParam:获取请求参数
例如,前端传值是这样的:
<a href="/testRequestParam?age=18&inters=basketball&inters=music">测试RequestParameter</a>
然后后端可以这样获取参数:
@GetMapping("/testRequestParam")
public Map<String, Object> testRequestParam(@RequestParam("age") Integer age,
@RequestParam("inters") List<String> inters,
@RequestParam Map<String, String> params) {
Map<String, Object> map = new HashMap<>();
map.put("age", age);
map.put("inters", inters);
map.put("params", params); //所有参数
return map;
}
2
3
4
5
6
7
8
9
10
ps,源码也有这样的注释:If the method parameter is Map <String, String> or MultiValueMap <String, String> and a parameter name is not specified, then the map parameter is populated with all request parameter names and values.
也就是方法中传了 Map、MultiValueMap,就会封装所有参数
测试效果:
这里 params 的 inters 少了一个值,这是因为我们用的是 Map <String, String>,而 key 是不能重复的,所以只有一个被存入了。改为 MultiValueMap 即可正常获取到所有值。
# @CookieValue:获取 Cookie
使用@CookieValue 注解,可以将 cookie 的值赋值给 String 类型,也可以直接赋值给一个 Cookie 对象。
首先,可以看看目前有什么 Cookie:打开控制台(F12),
然后复制一个 Cookie 的名称。后端代码:
@GetMapping("/testCookieValue")
public Map<String, Object> testCookieValue(
@CookieValue("Hm_lpvt_935c298d3de674300e25695d1ece4c34") String c,
@CookieValue("Hm_lpvt_935c298d3de674300e25695d1ece4c34") Cookie cookie) {
Map<String, Object> map = new HashMap<>();
map.put("c", c);
System.out.println(cookie.getName() + "----" + cookie.getValue());
return map;
}
2
3
4
5
6
7
8
9
前端代码:
<a href="/testCookieValue">测试testCookieValue</a>
测试效果:
# @RequestBody:获取请求体
前端代码:
<form action="/testRequestBody" method="post">
测试@RequestBody获取数据<br/>
<input type="text" name="username" placeholder="请输入用户名"> <br/>
<input type="text" name="email" placeholder="请输入邮箱"><br/>
<input type="submit" value="提交"><br/>
</form>
2
3
4
5
6
后端代码:
@PostMapping("/testRequestBody")
public Map<String, Object> testRequestBody(@RequestBody String content) {
Map<String, Object> map = new HashMap<>();
map.put("content", content);
return map;
}
2
3
4
5
6
测试结果:
格式之所以是这样子,因为浏览器发送的时候,表达数据就是这样的:可以在控制台看到
# @RequestAttribute:获取 request 域属性
有时候需要请求转发,并且在转发前需要存储一些数据,此时就可以存储到 request 域中。
演示:新建一个类
package com.peterjxl.boot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Controller
public class RequestController {
@GetMapping("/goto")
public String goToPage(HttpServletRequest request) {
request.setAttribute("msg", "成功了");
request.setAttribute("code", 200);
return "forward:/success"; //转发到 /success请求
}
@ResponseBody
@GetMapping("/success")
public Map<String, Object> testForward(@RequestAttribute("msg") String msg,
@RequestAttribute("code") Integer code,
HttpServletRequest request) {
Map<String, Object> map = new java.util.HashMap<>();
map.put("reqMethod_msg", msg);
map.put("annotation_msg", request.getAttribute("msg"));
return map;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
第一个方法中,存储了一些数据,然后转发请求到/success;
第二个方法中,则可以通过@RequestAttribute 来获取数据,也可以通过原生的 Servlet 来获取数据。
注意,此时不能方法中传个 Map,获取到所有值,没有这样的功能。
测试:访问 localhost: 8888/goto (opens new window),可以正常获取数据
不过一般我们是通过 EL 表达式,来获取和展示值
# 源码
已将本文源码上传到 Gitee (opens new window) 或 GitHub (opens new window) 的分支 demo12,读者可以通过切换分支来查看本文的示例代码
- 01
- 中国网络防火长城简史 转载10-12
- 03
- 公告:博客近期 RSS 相关问题10-02