会话
概念: 用户打开一个浏览器,访问多个web资源,关闭浏览器,这个过程称之为一个会话。
- 有状态会话
如: 一个同学来过教室,下次再来这个教室,我们会知道这个人曾经来过教室,类似的这称为有状态的会话。
- 无状态会话。(反之)
为什么需要会话控制?
即: 保持用户登录状态。
就是当用户在登录之后,会在服务器中保存该用户的登录状态,当
该用户后续访问该项目中的其它动态资源(Servlet或者Thymeleaf)的时候,能够判断当前是否是已经登录过的用户。
而从用户登录到用户退出登录这个过程中所发生的所有请求,其实都是在一次会话范围之内,即会话域。
会话域
会话域是从客户端连接上服务器开始,一直到客户端关闭,这一整个过程中发生的所有请求都在同一个会话域中;而不同的客户端是不能共用会话域的。
保存会话的两种技术
- Cookie:客户端技术(服务端响应给客户端,客户端下次访问带上)
- Session:服务端技术(服务端保存用户的信息或数据在session中)
Cookie
Cookie的概念
Cookie是一种客户端的会话技术,它是服务器存放在浏览器的一小份数据,浏览器以后每次访问该服务器的时候都会将这小份数据携带到服务器去。
Cookie的作用:
- 在浏览器中存放数据
- 将浏览器中存放的数据携带到服务器
Cookie的应用场景:
- 记住用户名:当我们在用户名的输入框中输入完用户名后,浏览器记录用户名,下一次再访问登录页面时,用户名自动填充到用户名的输入框
- 保存电影的播放进度:在网页上播放电影的时候,如果中途退出浏览器了,下载再打开浏览器播放同一部电影的时候,会自动跳转到上次退出时候的进度,因为在播放的时候会将播放进度保存到cookie中
- …
基本API介绍
- 服务端从请求中拿到cookie信息
- 服务器响应给客户端cookie。
Cookie[] cookies = req.getCookies();//得到所有的cookie对象。是一个数组,开发中根据key得到目标cookie
cookie.getName();//获得cookie中设置的key
cookie.getValue();//获得cookie中设置的value
new Cookie('','');//新建一个cookie对象,cookie只能保存字符串数据。且不能保存中文
cookie.setMaxAge('');//设置cookie的有效期
resp.addCookie(cookie);//响应给客户端一个cookie,若原来已存在cookie信息,再使用addCookie方法的话会覆盖原来的cookie信息。
- cookie一般保存在客户端本地的浏览器中。
注意:
- 一个cookie只能保存一个信息。(一个键值对信息)
- 一个web站点可以给浏览器发送多个cookie.
- cookie有大小限制,如4kb;
- 浏览器存储的cookie数目也是有上限的。
Cookie时效性:
如果我们不设置Cookie的时效性,默认情况下Cookie的有效期是一次会话范围内,即关闭浏览器,会自动失效。
我们可以通过cookie的setMaxAge(int expiry)
方法让Cookie持久化保存到浏览器上。
cookie.setMaxAge(int expiry)
参数单位是秒,表示cookie持久化时间,如果其中参数为0,表示将浏览器中保存的cookie删除。
示例删除Cookie:
- 需要先创建一个新的cookie对象,其key值需要和被删除的cookie的key相同.
- 通过setMaxAge() 设置Cookie有效期时间为0秒。
cookie.setPath("/");//这句话很关键,确保项目所有目录均有效,否则不敢保证删除。
new Cookie("被删除的cookie的key",'');//key要与被删除的一致
cookie.setMaxAge(0);
1)会话级Cookie
- 服务器端并没有明确指定Cookie的存在时间
- 在浏览器端,Cookie数据存在于内存中
- 只要浏览器还开着,Cookie数据就一直都在
- 浏览器关闭,内存中的Cookie数据就会被释放
2)持久化Cookie
- 服务器端明确设置了Cookie的存在时间
- 在浏览器端,Cookie数据会被保存到硬盘上
- Cookie在硬盘上存在的时间根据服务器端限定的时间来管控,不受浏览器关闭的影响
- 持久化Cookie到达了服务器端预设的时间就会被删除
Cookie的domain和path
上网时间长了,本地会保存很多Cookie。
对浏览器来说,访问互联网资源时不能每次都把所有Cookie带上。所以浏览器会使用Cookie的domain和path属性值来和当前访问的地址进行比较,从而决定是否携带这个Cookie。
这样浏览器就不用每次都把浏览器中所有的Cookie都带上。
我们可以通过调用cookie的setPath()
和setDomain()
方法来设置cookie的domain和path.
即如果一个Cookie调用了setPath("/user/"),那么浏览器只有在请求以/user/开头的路径时才会附加此Cookie。
Cookie示例案例
目标需求
实现在CookieDemo01和CookieDemo02之间共享数据,要求在会话域范围内共享。
代码如下:
CookieDemo01.java
在CookieDemo01中创建Cookie数据并响应给客户端
public class CookieDemo01 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 创建一个cookie对象,用于存放键值对
Cookie cookie = new Cookie("cookie-message","hello-cookie");
//2. 将cookie添加到response中
//底层是通过一个名为"Set-Cookie"的响应头携带到浏览器的
response.addCookie(cookie);
}
}
服务器将Cookie发送给客户端底层是通过一个名为"Set-Cookie"的响应头携带到浏览器的:
CookieDemo02.java
CookieDemo02获取Cookie数据的代码:
public class CookieDemo02 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 从请求中取出cookie
//底层是由名为"Cookie"的请求头携带的
Cookie[] cookies = request.getCookies();
//2. 遍历出每一个cookie
if (cookies != null) {
for (Cookie cookie : cookies) {
//匹配cookie的name
if (cookie.getName().equals("cookie-message")) {
//它就是我们想要的那个cookie
//我们就获取它的value
String value = cookie.getValue();
System.out.println("在CookieDemo02中获取str的值为:" + value);
}
}
}
}
}
浏览器会在给服务器发送请求的时候,将cookie通过请求头的Cookie参数自动携带到服务器,如下所示:
补充: 中文的编码处理问题
-
方式一: 通过 new String() 转编码处理
-
//例子(转换的中文参数需要转成字节) new String(xx.getBytes(),"utf-8");
-
-
方式二: 通过URLEncoder.encode()和URLDecoder.decode()方法
-
//例子 URLEncoder.encode("xxx","utf-8"); URLDecoder.decode("xxx","utf-8");
-
补充:对于不是字符串的数据输出,可以通过 非字符串数据+" " 拼接的形式将其转为字符串。
Session(重点)
概念:
-
服务器给每一个用户(浏览器)创建一个session对象,一个session对象独占一个浏览器,只要浏览器没有关闭,session就存在,用户登陆之后,整个网站它都可以访问。
-
session是服务器端的技术。服务器为每一个浏览器开辟一块内存空间,即session对象。由于session对象是每一个浏览器特有的,所以用户的记录可以存放在session对象中。
创建session:
req.getSession();//session对象
使用场景
- 保存一个用户的登陆信息
- 购物车信息
- 在整个网站中经常会使用的数据,我们将其放在session中
- …
Session的工作机制
前提:浏览器正常访问服务器
步骤:
1)服务器端没调用request.getSession()方法:
- 什么都不会发生
2)服务器端调用了request.getSession()方法:
- 服务器端检查当前请求中是否携带了JSESSIONID的Cookie
- 无:服务器端新建一个HttpSession对象作为request.getSession()方法的返回值返回
- 有:根据JSESSIONID在服务器端查找对应的HttpSession对象
- 能找到:将找到的HttpSession对象作为request.getSession()方法的返回值返回
- 找不到:服务器端新建一个HttpSession对象作为request.getSession()方法的返回值返回
Session对象常用API方法
request.getSession()//获得session对象(如果第一次调用的时候其实是创建session,第一次之后通过sessionId找到session进行使用)
session.getID();//获取sessionID
session.getServletContext();//通过session获取上下文对象
session.getAttribute();//获取存储在session中的属性对象
session.setAttribute();//设置存储在session中的属性对象
session.removeAttribute();//移除session的属性
session.invalidate();//使session过期失效
session.isNew();//判断是不是新的session
Session的时效性
为什么Session要设置时限
用户量很大之后,Session对象相应的也要创建很多。如果一味创建不释放,那么服务器端的内存迟早要被耗尽。
设置时限的难点
从服务器端的角度,很难精确得知类似浏览器关闭的动作。而且即使浏览器一直没有关闭,也不代表用户仍然在使用。
设置session失效的两种方式:
- 手动设置
//强制Session立即失效
session.invalidate();
- 通过配置文件web.xml设置session的默认失效时间
<!--设置Session的默认失效时间-->
<session-config>
<!--1分钟后Session自动失效,这里的时间以分钟为单位-->
<session-timeout>1</session-timeout>
</session-config>
服务器端给Session对象设置最大闲置时间
session.getMaxInactiveInterval()
获取session对象默认的最大闲置时间session.setMaxInactiveInterval(int time)
设置session对象的最大闲置时间,传入的数字参数是以分钟为单位的。
// ※测试时效性
// 获取默认的最大闲置时间
int maxInactiveIntervalSecond = session.getMaxInactiveInterval();
System.out.println("maxInactiveIntervalSecond = " + maxInactiveIntervalSecond);
// 设置默认的最大闲置时间
session.setMaxInactiveInterval(15);
Session的入门案例
目标需求:
实现在SessionDemo01和SessionDemo02之间共享数据,要求在会话域范围内共享。
代码如下:
SessionDemo01.java
SessionDemo01中往Session域对象存储数据:
public class SessionDemo01 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 获取Session对象
HttpSession session = request.getSession();
//2. 往Session对象中存入数据
session.setAttribute("session-message","hello-session");
}
}
SessionDemo02.java
在SessionDemo02中从Session域对象中获取数据:
public class SessionDemo02 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 获取Session对象
HttpSession session = request.getSession();
//2. 取出存在session对象中的数据,返回的类型默认为Object,需要手动进行强制类型转换
String message = (String)session.getAttribute("session-message");
System.out.println(message);
}
}
Session和Cookie的区别
- cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保留多个)
- session是把用户的数据写到用户独占的session中,服务器端保存(保存重要的信息)
- session对象由服务器创建(用户可以拿到sessionID,sessionID每个用户唯一),Session信息是存放在server端,但session id是存放在客户端的cookie中的。
The End!!创作不易,欢迎点赞/评论!!欢迎关注个人公众号