会话?
- 会话:用户打开浏览器,访问了一系列Web资源之后,关闭浏览器,在为了解cookie和session之前,这个过程可以称为一次会话。
- 有状态会话:浏览器访问某个服务器上的资源,服务器会产生访问记录,下次再访问这个服务器上的资源时,服务器知道之前访问过。
- HTTP协议是无状态的,所以需要Cookie和Session技术来保存会话信息,跟踪会话。
- 会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session,二者是并列关系,并不只有session代表会话。
- Cookie通过在客户端记录信息确定用户身份;
- Session通过在服务器端记录信息确定用户身份。
- 所以,了解了cookie和session的作用之后,一个用户的所有请求操作都应该属于一个会话,我们用cookie或者session来实现会话的跟踪。
- 当到期的cookie被清除之后,服务器不得不再次响应新的cookie(用户名和密码,或者session机制的sessionID),此时在概念上前后两次登录应该属于两次会话,但是为了保证用户的数据一致,应该会存在一种机制来将上次会话中的必要的数据同步到新的会话中(猜想:比如通过唯一的用户名进行识别,然后同步,数据都会在持久化文件中记录,在一次会话中存放在session中是为了增加访问速度)。
Cookie
简介?
- 客户端技术,cookie信息保存在客户端(浏览器缓存或者本地文件中),每次请求时会在请求头中携带cookie信息。在session出现之前,都是通过cookie跟踪会话的,此时用户的信息保存到cookie当中,相当于服务器端给该用户发放的通行证,服务器端通过该通行证识别用户。
- 利用cookie实现自动登录:用户名和密码保存到cookie当中(存活时间范围内都可以获取到),即在存活时间内都可以实现自动登录,请求时会携带记录用户名和密码的cookie,服务器端识别之后便自动进入登录状态。为了安全,通常会进行一些加密处理。
- 一个cookie类似一个键值对,记录一种信息,比如访问同一个web资源的次数。
- 在客户端记录着访问某个服务器的记录(缓存或者机器本地),访问服务器时,带着现有的cookie数据,由服务器解析封装到request请求中。
- 服务器端能从request获得自己想要的cookie,以及cookie的具体信息
- req.getCookies();获取所有cookie,一个cookie对应一个name-value。
- cookie.getName();获取某个cookie的name
- cookie.getValue();获取某个cookie的value
- 也可以通过response给浏览器添加cookie信息
- response.addCookie(new Cookie("name", "value"));
- cookie存储上限:
- 一台机器最多存储300个cookie信息
- 针对一个web站点(web服务器上的一个应用),浏览器可以为其存储的cookie数量也有上限。
- 一个cookie大小限制为4kb.
实例:获得浏览器上次访问时间
// 告诉浏览器上次访问时间
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求体的编码方式,必须在获取参数之前设置才能生效
req.setCharacterEncoding("UTF-8");
// 设置Writer写入到前端的数据的编码方式
resp.setContentType("text/html; charset=UTF-8");
// 获取输出流对象
PrintWriter out = resp.getWriter();
// 获取请求带来的cookie,通常情况下都有多个
Cookie[] cookies = req.getCookies();
// 获取上次访问时间
if(cookies != null){
// 有cookie,找到LastLoginTime对应的cookie,然后打印时间
for (int i = 0; i < cookies.length; i++) {
if("LastLoginTime".equals(cookies[i].getName())){
// 找到了
String value = URLDecoder.decode(cookies[i].getValue(), "UTF-8");
long valueL = Long.parseLong(value);
Date date = new Date(valueL);
// 这里的中文编码由resp.setContentType("text/html; charset=UTF-8")设置
out.write("上次访问的时间:" + date.toLocaleString());
break;
}
}
}else {
// 没有cookie信息,一般浏览器访问时都会有默认赋予的cookie信息
out.print("第一次访问该页面");
}
// 将此次访问时间存储到cookie中
long time = System.currentTimeMillis();
// URLEncoder.encode(time + "", "UTF-8") 如果是中文,制定编码格式为UTF-8;访问时,使用UTF-8解码
Cookie cookie = new Cookie("LastLoginTime", URLEncoder.encode(time + "", "UTF-8"));
// 添加一个cookie
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<servlet>
<servlet-name>cookieServlet</servlet-name>
<servlet-class>com.jing.servlet.CookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cookieServlet</servlet-name>
<url-pattern>/c1</url-pattern>
</servlet-mapping>
</web-app>
- 访问localhost:8080/cookie/c1
设置cookie有效期
- cookie默认的有效期是一次会话(浏览器关闭之前)
- 通过cookie.setMaxage(24 * 60 * 60); 可以设置cookie的存活时间为24小时,参数的单位秒。即使关闭浏览器,此cookie数据仍然不会被清除.
cookie本地存储位置
- ?cookie一般存储在本地目录的用户目录下:
- C:\Users\用户名\AppData\Local\Microsoft\Windows\History
cookie编码解码
- cookie的name和value都是String类型,应该通过统一编码和解码方式来防止出现中文乱码
- 编码:URLEncoder.encode(str, "UTF-8"); 返回的仍是一个字符串
- 解码:URLDecoder.decode(str, "UTF-8");
Session
简介
- session主要用来识别特定用户并跟踪用户的一次会话,专属于某个用户的数据可以记录在为其分配的session中(比如登录,购物车记录)。但并不是通过sessionID来区分不同用户,因为相同用户在不同会话中会有不同的sessionID,sessionID可以用来确保在同一台机器上不会重复登录。
- 浏览器登录网站之后,服务器端会为该浏览器生成一个session,用于存储用户的信息和数据,并且会在响应头中添加一个cookie用来记录sessionID,每次请求该站点的资源都会在请求头中携带改sessionID,用于在服务器端找到对应的session;
- 获取唯一session:request.getSession();
- 获取sessionID:session.getId();
- 向session中存储信息:session.setAttribute(String, Object);
- 从session中获取信息:session.getAttribute(name);
- 未登录状态下,Cookies中是没有sessionID的,?登录之后,会在响应头中添加一个sessionID的cookie。
- sessionID的cookie如果没有设置存活时间,默认情况下是关闭浏览器之后就会被清除,下次访问时,会重新分配sessionID,所以这两次会话的sessionID是不同的(浏览器关闭之前是一次会话);如果为该cookie设置了存活时间,如图2.3所示,该cookie的过期时间是2022年5月28日,所以关闭浏览器之后,该cookie仍然存在,下次打开浏览器访问该网站会携带同一个cookie(两次会话的sessionID相同),如图2.4所示是关闭浏览器再次访问相同网站,sessionID与图2.3中的相同(两次会话)。
- 利用sessionID实现自动登录:设置sessionID的cookie的存活时间,有效期范围内,相应的cookie没有被清除,下次访问会携带相同sessionID的cookie,服务器端识别之后便自动进入已登录状态。
- session也可以设置存活时间,在Web.xml中配置。到期清除该session后(可能会有大量不再使用的数据),会立即创建一个新session(无数据)。设置过期时间的好处之一是定时清理垃圾(用户量很大的网站session很占内存)。Tomcat默认是30分钟。
- 退出登录之后,记录sessionID的cookie也会被清除,虽然服务期端的session未被清除,但是由于没有sessionID,所以此时再去访问该网站(重新登录),会找不到原来的session。只能重新分配,于是会产生一个新的sessionID。此时也应该算是另一次会话。
- session(session中的数据)存储在服务器端,同一个应用的每个用户唯一,用来实现数据共享,此用户访问的该应用种所有Web资源(静态or动态servlet),都可以使用该session中的数据。
- session的作用域:某个应用中,一个用户对应一个session,不可以跨用户访问。同一个用户请求的所有servlet都可以获得该session,并设置/获取此session中的数据。所以用户独有的信息通常保存在session中。
- ServletContext(ApplicationContext)的作用域:应用范围内唯一,不区别用户。某个应用下的所有用户请求的所有servlet都可以访问。所以所有用户共有的数据可以保存在ServletContext中。
- 使用场景:
- 保存登录用户的信息
- 购物车信息
- 保存一个网站经常使用的信息,供所有web资源使用。
演示程序
- SessionServlet:获取session,并存储数据
public class SessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8");
PrintWriter out = resp.getWriter();
// 获取session
HttpSession session = req.getSession();
// 获取sessionID
String sessionId = session.getId();
// 向session中存数据
session.setAttribute("name", "于晶");
if(sessionId == null){
out.write("第一次访问");
}else {
out.write("不是第一次访问,sessionID为:" + sessionId);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
- SessionServletGetAttr:获取session,并获取数据,前提是该session中已经存在该数据
public class SessionServletGetAttr extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8");
PrintWriter out = resp.getWriter();
// 获取session
HttpSession session = req.getSession();
// 获取数据
String name = (String) session.getAttribute("name");
System.out.println(name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
- 注意:上述两个Servlet必须在同一个会话中被请求才会成功获取数据。?
注销session
????????可以通过session.invalidate();手动注销当前session,清理内存;但会立即产生一个新的空白session。
Cookie和Session的区别
- Cookie是客户端技术;Session是服务器端技术,二者是并列关系,都是用来记录用户的信息,跟踪整个会话过程。本来是没有联系的的,但是由于session实现会话跟踪需要依赖cookie,即sessionID放在cookie中,以便请求时携带,导致二者经常在一起讨论,cookie也是学习session的先验知识。
- 在一次会话中,一个浏览器针对同一个网站可以有多个Cookie,服务器为相同浏览器只分配一个Session。
- 一个cookie大小有限制,而且只能存String类型的name和value;session的大小没有限制,以String-Object类似于健值对的形式存数据,value值可以为任意类型。
- 如果Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。
- cookie持久化存储在客户端本地中,session存储在服务器内存中。
一个网站如何证明某个浏览器访问过???
|