什么是session
在我刚刚从事后端开发的时候,有一个问题困扰了我很久。
就有个玩意叫session。
@PostMapping("login")
public Result login(
@RequestParam("id") String id,
@RequestParam("password") String password,
HttpSession session) {
.......
}
每一个java程序员入门的时候。都会遇到这段代码。 刚刚开始接触后端开发,最最最简单 也最典型的入门 就是开发一个登录功能。
我容易理解的是 前端传一个请求过来会映射到这个方法,id 密码是前端输入之后传过来的。
然后我就懵逼了 我擦 这个HttpSession session玩意是从哪里冒出来的???这不是前端的参数列表吗??? 前端什么时候传了这么个玩意???
在解释HttpSession 之前,我们要理解一个东西 就是
Http 协议
在客户端和服务端 使用Http协议通信的时候,http协议的请求都是无状态的。 所谓无状态就是 它不会保留上一次请求的信息。每个HTTP请求都是独立的,服务器不会在不同的请求之间保存任何关于客户端的状态信息。这意味着服务器在处理每个请求时不会考虑之前的请求,也不会跟踪客户端的状态。每个请求都是相互独立的,服务器无法知道两个请求是否来自同一个客户端。
比如登录淘宝app 成功登进去了。 这就是一次http请求。
但是当你再发一次购物请求的时候, 对不起 淘宝的服务端 已经不认识你了。
除非给你一个窗口 你把刚才登录的用户名密码再发一遍 这样它就知道还是第一次登录的你了。
这就意味这 你在淘宝里面 做任何一次请求交互类的行为, 你都得把刚才登录的用户名密码再发一遍 。
这也太痛苦了对吧。
所以早期的网络交互技术中 就诞生了 session 的概念。 它就像一个短期的盒子 暂时让服务器记住你。 这样你就不用每次都带上用户名密码 让服务端认识你了。
当用户第一次访问服务端的时候, 服务器 会为他创建一个session。
这个session 你可以把它理解成一个 map结构。 它里面有key:sessionid 作为它的主键标识。 还有key是创建时间。比如
public String getId():返回包含唯一标识符值的字符串。
public long getCreationTime():返回创建此会话的时间,自格林威治标准时间 1970 年 1 月 1 日午夜起以毫秒为单位测量。
public long getLastAccessedTime():返回客户端最后一次发送与此会话关联的请求的时间,作为自格林威治标准时间 1970 年 1 月 1 日午夜以来的毫秒数。
public void invalidate():使这个会话无效,然后解除绑定到它的任何对象。
有意思的时候 你可以往这个session里面扔 key-value。 让它帮你存用户信息。你随时可以去取。 直到这个用户的访问会话结束 它才会销毁。
而服务器创建好session之后 它会把这个session id 发给前端。 存储在前端的cookie里面。
ok 现在回到那个淘宝的场景:
你登录之后 。第二次访问要买东西,不是无状态协议 第二次访问 服务器就不认识我了吗?? 这次我带着你给我的session id去找你。 通过session id 取出我第一次登录的时候存在session里面的信息。
你就认识我了对吧。
这就是 HttpSession , 所以当我们看到这段代码的时候要理解:
@PostMapping("login")
public Result login(
@RequestParam("id") String id,
@RequestParam("password") String password,
HttpSession session) {
.......
}
这个session 不是前端传过来的。 是后端你的tomcat服务器创建好之后 给你的, 你可以用也可以不用,看你的需要。
拓展
这里再给新玩家拓展一下, 你有没有想过 既然session是服务器创建的,那如果有多台服务器呢? 前端发一个请求过来, 后端有3个tomcat,使用nginx做负载均衡。 这时候你只有一台tomcat存了session 另外2台 第二次请求的时候还是 不认识你, 这时候怎么办呢?
解决思路有很多 常见的有两种:
- 多台tomcat之间 有session拷贝就可以 同步数据。(就像mysql集群同步数据一样)
- 使用redis来代替session 实现相同的功能(不知道redis的时候 可以去了解一下)