🔰 学习视频 🔰
尚硅谷雷神SpringBoot2零基础入门springboot全套完整版(spring boot2)
集数:25—42 (原理部分跳过)
🔰 学习笔记 🔰
文章目录
一、请求处理
1.1 请求映射
🔶 @xxxMapping
/getUser 获取用户
/deleteUser 删除用户
/editUser 修改用户
/saveUser 保存用户
🔶 Rest风格支持:使用HTTP请求方式动词来表示对资源的操作
/user
GET-获取用户
DELETE-删除用户
PUT-修改用户
POST-保存用户
🔶 Rest风格用法
1 表单method=post
,隐藏域 _method=put
2 SpringBoot中手动开启,配置文件
# 开启页面表单的Rest功能
spring:
mvc:
hiddenmethod:
filter:
enabled: true
🔶 Rest风格原理
请求过来被HiddenHttpMethodFilter
拦截,如果请求正常并且为POST
,获取到_method
的值(兼容PUT
.DELETE
.PATCH
请求,大小写均可)。原生模式的request(post),包装模式requestWrapper重写了getMethod方法,返回的是传入的值。过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
如果是Android直接发送,或者使用Postman客户端直接发送这些PUT
.DELETE
.PATCH
请求,不会经过filter
,所以页面表单的Rest功能可以选择性开启。
@GetMapping("/user")
等同于@RequestMapping(value = "/user",method = RequestMethod.GET)
@RequestMapping(value = "/user",method = RequestMethod.GET)
public String getUser(){
return "GET-张三";
}
@RequestMapping(value = "/user",method = RequestMethod.POST)
public String saveUser(){
return "POST-张三";
}
@RequestMapping(value = "/user",method = RequestMethod.PUT)
public String putUser(){
return "PUT-张三";
}
@RequestMapping(value = "/user",method = RequestMethod.DELETE)
public String deleteUser(){
return "DELETE-张三";
}
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
//自定义filter
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
methodFilter.setMethodParam("_m");
return methodFilter;
}
<form action="/user method="post">
<input name="_method" type="hidden" value="delete"/>
<input value="提交" type="submit"/>
</form>
🔶 扩展:如何把_method
这个名字换成_m
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
@Configuration(proxyBeanMethods = false)
public class WebConfig {
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
methodFilter.setMethodParam("_m");
return methodFilter;
}
}
1.2 请求映射原理
略
集数:28
1.3 基本注解
@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody
🔶 路径变量 @PathVariable
@RestController
public class ParameterController {
@GetMapping("/car/{id}/owner/{username}")
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("name", name);
map.put("pv", pv);
return map;
}
}
访问:localhost:8080/testPathVariable/1/owner/xxx
结果:
{"pv":{"id":"1","username":"xxx"},"name":"xxx","id":1}
🔶 请求头 @RequestHeader
@GetMapping("/testRequestHeader/{id}")
public Map<String, Object> testRequestHeader(@PathVariable("id") Integer id,
@RequestHeader("User-Agent") String userAgent,
@RequestHeader Map<String, String> pv) {
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("userAgent", userAgent);
map.put("pv", pv);
return map;
}
访问:localhost:8080/testRequestHeader/1
结果:
{"pv":{"host":"localhost:8080","connection":"keep-alive","sec-ch-ua":"\"Google Chrome\";v=\"95\", \"Chromium\";v=\"95\", \";Not A Brand\";v=\"99\"","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\"Windows\"","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","sec-fetch-site":"none","sec-fetch-mode":"navigate","sec-fetch-user":"?1","sec-fetch-dest":"document","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7","cookie":"Idea-11f3a2b2=09893cd1-2e09-40b2-9024-ec951cc04a73; JSESSIONID=FF70BC34EC9A540598FB6B3F29D9C73B; token=19fcec7bda5bef324bdb9af9c6ebf25d"},"userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36","id":1}
🔶 请求参数 @RequestParam
@GetMapping("/testRequestParam")
public Map<String, Object> testRequestParam(@RequestParam("id") Integer id,
@RequestParam("list")List<String> list,
@RequestParam Map<String, String> pv) {
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("list", list);
map.put("pv", pv);
return map;
}
访问:localhost:8080/testRequestParam?id=1&list=l1&list=l2
结果:
{"pv":{"id":"1","list":"l1"},"id":1,"list":["l1","l2"]}
🔶 Cookie值 @CookieValue
@GetMapping("/testCookieValue")
public Map<String, Object> testCookieValue(@CookieValue("JSESSIONID") String JSESSIONID,
@CookieValue("JSESSIONID") Cookie cookie) {
Map<String, Object> map = new HashMap<>();
System.out.println(cookie);
map.put("JSESSIONID", JSESSIONID);
return map;
}
访问:localhost:8080/testCookieValue
结果:
{"JSESSIONID":"FF70BC34EC9A540598FB6B3F29D9C73B"}
控制台输出:
javax.servlet.http.Cookie@a7fcf7c
🔶 请求体 @RequestBody
@PostMapping("/save")
public Map<String, Object> postMethod(@RequestBody String content) {
Map<String, Object> map = new HashMap<>();
map.put("content", content);
return map;
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/save" method="post">
username:<input type="text" name="username"/><br>
email:<input type="email" name="email"/><br>
<input type="submit">
</form>
</body>
</html>
测试
结果
🔶 请求域属性 @RequestAttribute
通过/goto
发送请求,并进行setAttribute
,然后将请求转发给/success
;在success
中获得转发前的请求。
@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 success(@RequestAttribute("msg") String msg,
@RequestAttribute("code") Integer code,
HttpServletRequest request) {
Map<String,Object> map = new HashMap<>();
Object msg1 = request.getAttribute("msg");
map.put("reqMethod_msg", msg1);
map.put("annotation_msg", msg);
return map;
}
}
结果:
{"reqMethod_msg":"成功了...","annotation_msg":"成功了..."}
🔶 矩阵变量 @MatrixVariable
配置:
@Configuration(proxyBeanMethods = false)
public class WebConfig{
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
// 不处理";"后面的内容,矩阵变量功能就可以实现了。
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
};
}
}
案例1
控制器:
@GetMapping("/cars/{path}")
public Map testMatrixVariable(@MatrixVariable("low") Integer low,
@MatrixVariable("brand") List<String> brand,
@PathVariable("path") String path) {
Map<String, Object> map = new HashMap<>();
map.put("low", low);
map.put("brand", brand);
map.put("path", path);
return map;
}
访问:http://localhost:8080/cars/sell;low=34;brand=byd,audi,yd
结果:
{"path":"sell","low":34,"brand":["byd","audi","yd"]}
案例2
两个路径有相同的属性,如何指定获取。
//访问: /boss/1;age=20/2;age=10
@GetMapping("/boss/{bossId}/{empId}")
public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
@MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
Map<String,Object> map = new HashMap<>();
map.put("bossAge",bossAge);
map.put("empAge",empAge);
return map;
}
二、响应处理
2.1 响应JSON
所需依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Web场景自动引入了Json场景
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
控制类:
@Controller
public class ResponseController {
@ResponseBody
@GetMapping("/test/person")
public Person getPerson() {
Person person = new Person();
person.setAge(28);
person.setBirth(new Date());
person.setUserName("xxx");
return person;
}
}
结果:
{"userName":"xxx","age":28,"birth":"2021-11-06T10:31:08.327+00:00"}
2.2 内容协商
根据客户端接收能力不同,返回不同媒体类型的数据。
导入依赖:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
控制类:
@Controller
public class ResponseController {
@ResponseBody
@GetMapping("/test/person")
public Person getPerson() {
Person person = new Person();
person.setAge(28);
person.setBirth(new Date());
person.setUserName("xxx");
return person;
}
}
根据客户端请求头中Accept字段,来返回对应的结果。Http协议中规定的,告诉服务器本客户端可以接收的数据类型。如果客户端要接收xml,则返回xml;如果客户端要接收json,则返回json。