Spring Web MVC 是基于 Servlet 构建的原始 Web 框架, 包含在 Spring 框架中.
Spring Web MVC 来自其源模块的名称(Spring-webmvc), 但通常称作 Spring MVC
即
MVC(Model View Controller)—模型视图控制器
MVC 与 Spring MVC 之间的关系类似于 IOC(思想) 与 DI(思想的具体实现) 之间的关系
MVC 是一种思想
Spring MVC 是对 MVC 思想的具体实现
利用 Spring MVC 输出 hello world
在 demo 包下创建一个 controller 包
在 controller 包下创建一个 TestController 类
demo(package) → controller(package) → TestController(.class)
@Controller
, 存储 TestController 至 Spring 容器@ResponseBody
, 返回数据而非页面@RequestMapping()
, 设置请求路径注意
@Controller
可与@ResponseBody
合并为@RestController
@RequestMapping()
既可以修饰类也可以修饰方法完整代码
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
// @Controller
// @ResponseBody
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/hello")
public String sayHello() {
return "hello world";
}
}
运行结果
@RequestMapping 默认情况下支持多种 HTTP 请求
包括 GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS…
可通过 Postman 工具进行查看
通过 method 属性指定请求的类型
可指定的请求类型
举个栗子
指定 GET 请求method = RequestMethod.GET
完整代码
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String sayHello() {
return "hello world";
}
}
另一种指定 GET 请求的方式
(其他类型同理)
@GetMapping("/hello")
效果与@RequestMapping(value = "/hello", method = RequestMethod.GET)
相同
此时通过其他请求进行访问就会报错
405(Method Not Allowed)—方法不被允许
@RestController
@RequestMapping("/test")
public class TestController {
// 获取单个参数
@GetMapping("/hello")
public String sayHello(String name) {
return "hello " + name;
}
}
注意
URL 中的 key 必须与所传参数一致
错误示范
@RestController
@RequestMapping("/test")
public class TestController {
// 获取两个参数
@GetMapping("/hello")
public String sayHello(String name, Integer age) {
return "hello name: " + name + " | age: " + age;
}
}
注意
建议传参的类型为包装类型, 而非基础类型
错误示范
当传参的类型为基础类型时
// 获取两个参数
@GetMapping("/hello")
public String sayHello(String name, int age) {
return "hello name: " + name + " | age: " + age;
}
当传参的类型为包装类型时
// 获取两个参数
@GetMapping("/hello")
public String sayHello(String name, Integer age) {
return "hello name: " + name + " | age: " + age;
}
利用注解@RequestParam
为参数重命名
举个栗子
有两个参数 String t1(起始时间), String t2(结束时间)
滑稽老哥觉得 t1, t2 这两个名字不太好, 想要改成 startTime, endTime
于是利用注解@RequestParam
为参数重命名
将 t1 重命名为 startTime
将 t2 重命名为 endTime
@GetMapping("time")
public String showTime(
@RequestParam(value = "t1", required = false) String startTime,
@RequestParam(value = "t2", required = false) String endTime) {
return "开始时间: " + startTime + " | 结束时间: " + endTime;
}
对于 required 的解释
分析@RequestParam()
源码发现, required
默认为 true
即忘记填写对应的 key 时就会报错
设置required
为 false
当所需获取的参数较多时, 可通过传递对象的方式进行传参
设置对象属性
@Data
public class User {
private int id;
private String name;
private int age;
}
传递对象
@RestController
@RequestMapping("/test")
public class TestController {
// 传递对象
@GetMapping("/user")
public String showUser(User user) {
return user.toString();
}
}
注意
URL 中的 key 必须与所传对象的属性一致
错误示范
利用注解@RequestBody
传递 JSON 对象
@RestController
@RequestMapping("/test")
public class TestController {
// 传递 JSON 对象
@PostMapping("/json-user") // 推荐使用 @PostMapping
public String showJsonUser(@RequestBody(required = false) User user) {
return user.toString();
}
}
注意
此处不建议使用@GetMapping
传递 JSON 对象 , @GetMapping
默认使用 URL 传递参数
http://127.0.0.1:8080/test/login?username=bibubibu
http://127.0.0.1:8080/test/login/bibubibu
此处所指获取 URL 中的参数是后者的形式
即/
后面就是参数, 而不是?username=bibubibu
利用注解@PathVariable
获取 URL 中的参数
举个栗子
需要传递的参数用 { } 包裹
{username}
{password}
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/login/{username}/{password}")
public String login(
@PathVariable(value = "username", required = false) String username,
@PathVariable(value = "password", required = false) String password) {
return "username: " + username + " | password: " + password;
}
}
利用注解@RequestPart
上传文件
@RestController
@RequestMapping("/test")
public class TestController {
// 上传文件
@RequestMapping("/upfile")
public String upFile(@RequestPart("files") MultipartFile file) throws IOException {
// 1. 根目录
String path = "D:\\Java\\documents\\png_file\\";
// 2. 根目录 + 唯一文件名
path += UUID.randomUUID().toString().replace("-", "");
// 3. 根目录 + 唯一文件名 + 文件后缀
path += file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
// 4. 保存文件
file.transferTo(new File(path));
return path;
}
}
Spring MVC 内置了 HttpServletRequest, HttpServletResponse
传统方式获取 Cookie—通过 Servlet 获取(获取全部 Cookie)
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/getCookies")
public String getCookies(HttpServletRequest req) {
Cookie[] cookies = req.getCookies();
for(Cookie item : cookies) {
log.error(item.getName() + " | " + item.getValue());
}
return "getCookies~~";
}
}
校验
添加 Cookie
运行查看结果
利用注解获取 Cookie—通过@CookieValue
获取(获取指定 Cookie)
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/getCookie")
public String getCookie(@CookieValue("Homo") String val) {
log.error("Homo | " + val);
return "getCookie~~";
}
}
运行查看结果
传统方式获取 header—通过 Servlet 获取
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/getUser-Agent")
public String getHeader(HttpServletRequest req) {
String userAgent = req.getHeader("User-Agent");
return "tradition | UserAgent : " + userAgent;
}
}
运行查看结果
利用注解获取 header—通过@RequestHeader
获取
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/getUser-Agent")
public String getUA(@RequestHeader("User-Agent") String userAgent) {
return "Annotation | UserAgent : " + userAgent;
}
}
运行查看结果
利用 Servlet 存储 Session
对于getSession()
, getSession(true)
, getSession(false)
的解释
getSession(true)
, 如果当前含有 HttpSession, 使用当前 HttpSession, 如果没有, 新创建 SessiongetSession(false)
, 如果当前含有 HttpSession, 使用当前 HttpSession, 如果没有, 返回 NullgetSession()
, 等同于getSession(true)
@RestController
@RequestMapping("/test")
public class TestController {
// 通过 Servlet 存储 Session
@RequestMapping("/setSession")
public String setSession(HttpServletRequest req) {
// 如果当前含有 HttpSession, 使用当前 HttpSession, 如果没有, 新创建 Session
HttpSession session = req.getSession(true);
// 设置 key, value
session.setAttribute("userInfo", "userInfo");
return "Set Session Success";
}
}
获取 Session 有 2 种方式
@SessionAttribute
获取@RestController
@RequestMapping("/test")
public class TestController {
// 通过 Servlet 获取 Session
@RequestMapping("/getSession")
public String getSession(HttpServletRequest req) {
HttpSession session = req.getSession(false);
if(session != null && session.getAttribute("userInfo") != null) {
return (String) session.getAttribute("userInfo");
} else {
return "session 信息不存在";
}
}
}
@RestController
@RequestMapping("/test")
public class TestController {
// 通过 @SessionAttribute 获取 Session
@RequestMapping("/getSession")
public String getSession(
@SessionAttribute(value = "userInfo", required = false) String userInfo) {
return userInfo;
}
}
@ResponseBody
, 返回页面@ResponseBody
, 返回数据返回页面
(未添加@ResponseBody
)
@RequestMapping("/resp")
@Controller
public class RespController {
@RequestMapping("/page")
public String retPage() {
return "/hello.html";
}
}
返回数据
(添加@ResponseBody
)
@RequestMapping("/resp")
@Controller
@ResponseBody
public class RespController {
@RequestMapping("/page")
public String retPage() {
return "/hello.html";
}
}
返回 对象(Object) / HashMap 都是 JSON 格式
JSON 格式是键值对结构, 对象(Object) / HashMap 也是键值对结构
以 HashMap 为例
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/response")
public HashMap<String, String> respJson() {
HashMap<String, String> map = new HashMap<>();
map.put("Tom", "Tom_Val");
map.put("Homo", "Homo_Val");
map.put("Jack", "Jack_Val");
return map;
}
}
抓包查看结果
请求转发
// 请求转发
@RequestMapping("/bibubibu-forward")
public String reqForward() {
return "forward:/hello.html";
}
请求重定向
// 请求重定向
@RequestMapping("/bibubibu-redirect")
public String reqRedirect() {
return "redirect:/hello.html";
}
举个栗子
滑稽老哥对他女朋友说想吃羊肉串
女朋友帮他买羊肉串(请求转发)
滑稽老哥自己去买羊肉串(请求重定向)
具体区别
类似于滑稽老哥自己去买羊肉串他就能买到口感最好的羊肉串(自己平时光顾较多的烧烤店) → 原外部资源能够访问
而委托女朋友去买虽然告诉了具体的地址仍然有可能买错 → 原外部资源不能访问
@RestController
→ @Controller
+ @ResponseBody
@RequestMapping
默认支持多种 HTTP 请求(GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS…)@RequestMapping
指定请求类型 → @RequestMapping(value = "", method = RequestMethod.指定请求的类型)
@RequestMapping
指定请求类型 == 指定请求类型Mapping@RequestMapping(value = "", method = RequestMethod.GET)
== @GETMapping(value = "")
)@RequestParam
@RequestBody
@PathVariable
@RequestPart
@CookieValue
获取(获取指定 Cookie)@RequestHeader
获取@SessionAttribute
获取@ResponseBody
→ 未添加@ResponseBody
, 返回页面 / 添加@ResponseBody
, 返回数据完结撒花