博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Session Java
阅读量:2207 次
发布时间:2019-05-04

本文共 3173 字,大约阅读时间需要 10 分钟。

首先,Session 是什么?

简单地说,Session(会话) 是服务器用于辨识用户的一个手段


为 什 么 要 使 用 S e s s i o n \color{blue}{为什么要使用Session} 使Session

HTTP请求是stateless的

也就是说谁都可以向服务器发送HTTP请求

接触过爬虫的朋友应该都能理解

像python中的requests.get(url)就相当于发送了一个HTTP请求

但是,这样单纯的交互只是一次性的

也就是,你发送一次HTTP请求,服务器回应你一次

你再次向同一个服务器发送HTTP请求时,服务器并不知道你是之前交流过的用户

这并不是我们想要的

因为一般情况下,我们与服务器之间的交互肯定不止一次

我从宏观角度举一个例子:

我登录上了的淘宝网

然后找到了想要的商品,正要购买时,网站提示我又要登录

??我不是已经登陆了吗??

嗯 就是这个意思


S e s s i o n 是 怎 么 使 用 的 \color{red}{Session是怎么使用的} Session使

那么,服务器怎么知道我就是之前和他有交互的用户呢?

可以通过Session(会话)

当我们第一次向服务器发送HTTP请求的时候,服务器会返回一个response给我们

在这个response中,会有一个session的ID,用于标识

(当然,不是所有服务器都会做这个操作,我这只讲有的情况)

这个其实我们可以直观看到

在Response Headers中你可以看见:

Connection: keep-aliveContent-Length: 142Content-Type: text/html;charset=UTF-8Date: Fri, 16 Oct 2020 13:24:08 GMTKeep-Alive: timeout=20Set-Cookie: JSESSIONID=E0DA20B59AF009AC7827C184946633F6; Path=/EE_learn; HttpOnly

Set-Cookie: JSESSIONID=E0DA20B59AF009AC7827C184946633F6; Path=/EE_learn; HttpOnly

没错,这个是Session (会话)的ID是服务器生成并且设置在Cookie中的

并且这个Set-Cookie操作只会在Session(会话)开始之时进行

你再次刷新页面查看的时候,在Response Headers中是无法再看到的

这时,你就得到Request Headers 中的Cookies 中去找了

Cookie: JSESSIONID=E0DA20B59AF009AC7827C184946633F6

那么,只要你每个HTTP请求都带上这个ID(这个工作浏览器会帮我们完成)

服务器就可以知道你是老用户了


不过,现在大部分的网站都不会只是通过Session的ID来辨识用户(不然,这个网站三下两下得被爬虫搞崩)

还会在Cookies中添加类似SessionID的别的一些凭证(很多爬虫就是卡在了这一关上)

对了,不要被我上面举的例子误导,SessionID并一定是 JSESSIONID

JSESSIONID 只是Tomcat服务器上Servelet 生成的SessionID

其他服务器各有不同


S e s s i o n 的 生 命 周 期 \color{red}{Session的生命周期} Session

虽然我上面一直都在讨论SessionID,但实际上Session是一个对象

它有自己的生命周期

当第一次请求时,服务器会生成

那么什么时候结束呢?

有三个方法

1.timeout

服务器在设置SessionID的时候还设置了一个timeout

时间一过,Session便会被销毁

不同服务器timeout规则可能不一样

对于Tomcat 是可以在web.xml中配置这个timeout的

30

单位是分钟

2.客户端销毁Session

我们退出浏览器就可以销毁当前的Session(会话)了

注意是退出浏览器,而不是单单关闭页面

(复制好链接,退出浏览器,打开浏览器,粘贴链接,此时相当于第一次请求,会生成新的Session)

对了,有一些网站,你尽管退出了浏览器,但重新进入网站,还是处于登录状态,多半是因为Cookies

关闭浏览器会销毁的是当前Session,而Cookies是浏览器可以保存在本地的

3.服务器端销毁Session

调用Session对象的invalidate()方法即可销毁当前Session

补充:

其实,这个SessionID不一定是储存在Cookies里

还可以在URL的参数中

在response对象中便有一个encodeURL()方法用于生成SessionID(也是在第一次请求的情况下)

在doGet()方法中可以这么调用encodeURL()

response.encodeURL(HttpUtils.getRequestURL(request).toString())

不 建 议 使 用 S e s s i o n 的 A t r r i b u t e \color{red}{不建议使用Session的Atrribute} 使SessionAtrribute

确实,Session提供了setAttribute()和getAttribute() 方法

但是,却不建议使用

包括context对象中的Atrribute 一样不建议使用

因 为 C o n t e x t 和 S e s s i o n 都 不 是 线 程 安 全 的 \color{blue}{因为Context和Session都不是线程安全的} ContextSession线

理解这个之前,还得先了解一下Servlet的机制

每个Servlet只有一个实例,当同时有多个请求时,Tomcat容器会为每个请求分配一个线程

(Tomcat容器是有一个线程池用来处理请求的)

然后,用户与服务器之间的交互其实是多线程并发

那么对于Session这样的共享变量来说

则需要考虑考虑同步的问题

而Tomcat 本身对于Session并不会上锁

如果我们忽略了这一点的话,就有可能会出现错误

真要用Session的Attribute也行,得自己上锁就是了

(我有实际测试的例子,但是。。一下关联到几个文件,说明起来有点麻烦,有需要再留言吧)

那。。。Attribute还有什么用?

r e q u e s t 里 的 A t t r i b u t e 是 线 程 安 全 的 \color{blue}{request里的Attribute是线程安全的} requestAttribute线

容器会为每个请求创建两个对象:HttpServletResponse and HttpServletRequest

也就是我们常见的request和response

当同时有多个请求的时候,容器会各自为其分配线程

同时,还会为每个线程创建各自的HttpServletResponse和HttpServletRequest的实例

即request是每个线程里的局部变量(其实是个对象啦,只是侧重点在局部)

和session这个共享变量是有区别的

所以,使用request里的Attribute时,就不用担心线程安全问题了

我们可以放心地用request在多个servlet之间传递


各个编程语言有各个编程语言自己的风格

转载地址:http://kliyb.baihongyu.com/

你可能感兴趣的文章
硬盘的接口、协议
查看>>
VLAN与子网划分区别
查看>>
Cisco Packet Tracer教程
查看>>
02. 交换机的基本配置和管理
查看>>
03. 交换机的Telnet远程登陆配置
查看>>
微信小程序-调用-腾讯视频-解决方案
查看>>
phpStudy安装yaf扩展
查看>>
密码 加密 加盐 常用操作记录
查看>>
TP 分页后,调用指定页。
查看>>
Oracle数据库中的(+)连接
查看>>
java-oracle中几十个实用的PL/SQL
查看>>
PLSQL常用方法汇总
查看>>
几个基本的 Sql Plus 命令 和 例子
查看>>
PLSQL单行函数和组函数详解
查看>>
Oracle PL/SQL语言初级教程之异常处理
查看>>
Oracle PL/SQL语言初级教程之游标
查看>>
Oracle PL/SQL语言初级教程之操作和控制语言
查看>>
Oracle PL/SQL语言初级教程之过程和函数
查看>>
Oracle PL/SQL语言初级教程之表和视图
查看>>
Oracle PL/SQL语言初级教程之完整性约束
查看>>