Spring Web MVC
1 Spring MVC 使用
1.1 获取 URL 中的参数 @PathVariable
path Variable:路径变量,主要作用在请求 URL 路径上的数据绑定。
后端实现代码:
java
package com.example.demo;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/m8/{id}/{name}")
public String method8(@PathVariable Integer id,@PathVariable("name") String userName) {
return "解析参数id:" + id + ",name:" + userName;
}
}
发送请求:http://127.0.0.1:8080/param/m8/5/zhangsan

1.2 上传文件 @RequestPart
后端代码实现:
java
package com.example.demo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/m9")
public String getfile(@RequestPart("file") MultipartFile file) throws IOException {
//获取文件名称
String fileName = file.getOriginalFilename();
//文件上传到指定路径
file.transferTo(new File("D:/Java/" + file.getOriginalFilename()));
return "接收到文件名称为:" + fileName;
}
}
发送请求:

观察 D:/Java/ 路径


1.3 获取 Cookie/Session
回顾 Cookie
HTTP 协议自身是属于无状态协议,默认情况下,HTTP 协议的客户端和服务器之间的这次通信,和下一次通信之间没有直接的联系。但在实际开发中,很多时候是需要知道请求之间的关联关系的。

上述图中的"令牌"通常就存储在 Cookie 字段中,此时服务区需要登记"令牌"信息,以及令牌对应的用户信息。
理解 Session
在计算机领域,会话是一个客户与服务器之间的不中断的请求响应。对客户的每个请求,服务器能够识别除请求来自同一个客户。当一个未知的客户向 Web 应用程序发送第一个请求时就开始了一个会话。当客户明确结束会话或者服务器在一个时限内没有接收到客户的任何请求时,会话就结束了。

服务器在同一时刻收到的请求是很多的,服务器需要清楚的区分每个请求属于哪个用户,也就是属于哪个会话,就需要在服务器这边记录每个会话以及与用户的对应关系。Session 是服务器为了保护用户信息而创建的一个特殊的对象。

Session 的本质就是一个"哈希表",存储了一些键值对结构。Key 就是 SessionID,Value 就是用户信息(用户信息可以根据需求灵活设计)

SessionID 是由服务器生成的一个"唯一性字符串",从 Session 机制的角度来看,这个唯一性字符串称为"token"。

(1)当用户登录的时候,服务器在 Session 中新增一个记录,并把 sessionID 返回给客户端(通过 HTTP 响应中的 Set-Cookie 字段返回)
(2)客户端后续再给服务器发送请求的时候,需要在请求中带上 sessionID (通过 HTTP 请求中的 Cookie 字段带上)
(3)服务器收到请求之后,根据请求中的 sessionID 在 Session 信息中获取到对应的用户信息,再进行后续操作,找不到则重新创建 Session,并把 SessionID 收回

Session 默认是保存在内存中的,如果重启服务器则 Session 数据就会丢失。
Cookie 和 Session 的区别
(1)Cookie 是客户端保存用户信息的一种机制, Session 是服务器端保护用户信息的一种机制
(2)Cookie 和 Session 之间主要通过 SessionID 关联起来的,SessionID 是 Cookie 和 Session 之间的桥梁
(3)Cookie 和 Session 经常会在一起配合使用,但是不是必须的。完全可以用Cookie 来保存一些数据在客户端,这些数据不一定是用户身份信息,也不一定是 SessionId。Session 中的 sessionId 也不需要非得通过 Cookie/Set-Cookie 传递。
获取 Cookie
传统获取 Cookie
java
package com.example.demo;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.http.HttpRequest;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/m10")
public String method10(HttpServletRequest request, HttpServletResponse response) {
//获取所有 cookie 信息
Cookie[] cookies = request.getCookies();
//打印cookie信息
StringBuilder builder = new StringBuilder();
if(cookies != null) {
for(Cookie ck : cookies) {
builder.append(ck.getName() + ":" + ck.getValue());
}
}
return "Cookie信息:" + builder;
}
}
Spring MVC 是基于 Servlet API 构建的原始 Web 框架,也是在 Servlet 的基础上实现的。HttpServletRequest,HttpServletResponse 是 Servlet 提供的两个类,是 Spring MVC 方法的内置对象,需要时直接在方法中添加声明即可。
HttpServletRequest 对象代表客户端的请求,当客户端通过 HTTP 协议访问服务器时,HTTP 请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。
HttpServletResponse 对象代表服务器的响应,HTTP 响应的信息都在这个对象中,比如向客户端发送的数据,响应头,状态码等,通过这个对象提供的方法,可以获得服务器响应的所有内容。Spring MVC 在这两个对象的基础上进行了封装,提供了更加简单的使用方法。
此时没有设置 Cookie,通过浏览器访问:

设置一下Cookie的值

再次访问:

可以看出 Cookie 是可以伪造的,也就是不安全的,所以使用 Cookie 是,后端需要进行 Cookie 校验
简洁获取 Cookie
java
package com.example.demo;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.http.HttpRequest;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/getCookie")
public String cookie(@CookieValue("bite") String bite) {
return "bite:" + bite;
}
}
运行结果:http://127.0.0.1:8080/param/getCookie

获取 Session
Session 是服务器端的机制,需要先存储,才能获取。
Session 也是基于 HttpServletRequest 来存储和获取的
Session 存储
java
package com.example.demo;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.http.HttpRequest;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/setSess")
public String setsess(HttpServletRequest request) {
//获取Session对象
HttpSession session = request.getSession();
if(session != null) {
session.setAttribute("username","java");
}
return "session 存储成功";
}
}
这个代码中看不到 SessionID 这样的概念。getSession 操作内部提取到请求中的 Cookie 里的 SessionID,然后根据 SessionID 获取到对应的 Session 对象,Session对象用 HttpSession 来描述。

获取 Session 有两种方式

HttpSession getSession(boolean create):参数如果为 true,则当不存在会话时新建会话;参数如果为 false,则当不存在会话时候,返回 null
HttpSession getSession():和 getSession(true) 含义一样,默认值为 true
void setAttribute(String name,Object value):使用知道的名称绑定一个对象到该 session 会话。
Session 读取
读取 Session 可以使用 HttpServletRequest
java
package com.example.demo;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.http.HttpRequest;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/getSess")
public String sess(HttpServletRequest request) {
//如果 session 不存在,不会自动创建
HttpSession session = request.getSession(false);
String username = null;
if(session != null && session.getAttribute("username") != null) {
username = (String) session.getAttribute("username");
}
return "username:" + username;
}
}
ObjectgetAttribute(String name):返回再该 session 会话中具有指定名称的对象,如果每指定名称的对象,则返回 null 。
运行
先设置 Session :http://127.0.0.1:8080/param/setSess

HTTP响应中,通过 Set-Cookie 告知客户端,把 SessionID 存储在 Cookie 中


通过浏览器可以观察到运行结果

获取 Session:http://127.0.0.1:8080/param/getSess

Http请求时,把 SessionID 通过 Cookie 传递到了服务器


简洁获取 Session(1)
java
package com.example.demo;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.http.HttpRequest;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/getSess2")
public String sess2(@SessionAttribute(value = "username",required = false)
String username) {
return "username:" + username;
}
}
运行结果:http://127.0.0.1:8080/param/getSess2

简洁获取 Session(2)
通过 Spring MVC 内置对象 HttpSession 来获取
java
package com.example.demo;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.http.HttpRequest;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/getSess3")
public String sess3(HttpSession session) {
String username = (String) session.getAttribute("username");
return "username:" + username;
}
}
运行结果:http://127.0.0.1:8080/param/getSess3

1.4 获取 Header
传统获取 header
获取 Header 也是从 HttpServletRequest 中获取
java
package com.example.demo;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.http.HttpRequest;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/param10")
public String param10(HttpServletRequest request,HttpServletResponse response) {
String userAgent = request.getHeader("User-Agent");
return "userAgent:" + userAgent;
}
}
运行结果:http://127.0.0.1:8080/param/param10


简洁获取 Header
java
package com.example.demo;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.http.HttpRequest;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String userAgent) {
return "userAgent:" + userAgent;
}
}
