1.概念分析
跟踪用户状态指的是web应用能够分辨请求属于哪个用户,进而记录用户的状态,从而为用户提供连续的针对性的服务。比如有多个客户在同一个购物网站上购物,每一个用户都会有一个虚拟的购物车。当某个客户发送请求将商品添加到购物车时,Web服务器必须能识别请求属于哪个用户,从而将商品添加该用户的购物车中
大多数的Web应用都需要跟踪用户状态,才能提供对应的服务。常见需要跟踪用户状态的应用:
-
电子商务
-
管理系统
也有一些简单的Web应用不需要跟踪用户状态。一些不需要跟踪用户状态的应用:
-
门户新闻网站
-
软件下载网站
2.http协议无状态
http协议是无状态的。每发起一次请求,就就创建一个新的连接,当结果响应结束后,连接就会被关闭。1个用户的多次请求和多个用户各发1次请求对于Web服务器而言是没有区别的。Web服务器无法根据连接分辨请求属于哪一个用户,http协议本身没有分辨用户,跟踪用户状态的功能。
解决方案:
-
Cookie
-
HttpSession
3 Cookie
Cookie 并不是它的原意“甜饼”的意思, 而是一个保存在客户机中的简单的文本文件, 这个文件与特定的 Web 文档关联在一起, 保存了该客户机访问这个Web 文档时的信息, 当客户机再次访问这个 Web 文档时这些信息可供该文档使用。由于“Cookie”具有可以保存在客户机上的神奇特性, 因此它可以帮助我们实现记录用户个人信息的功能 。
举例来说, 一个 Web 站点可能会为每一个访问者产生一个唯一的ID, 然后以 Cookie 文件的形式保存在每个用户的机器上。如果使用浏览器访问 Web, 会看到所有保存在硬盘上的 Cookie。在这个文件夹里每一个文件都是一个由“名/值”对组成的文本文件,另外还有一个文件保存有所有对应的 Web 站点的信息。在这里的每个 Cookie 文件都是一个简单而又普通的文本文件。透过文件名, 就可以看到是哪个 Web 站点在机器上放置了Cookie(当然站点信息在文件里也有保存) 。
所谓“cookie”数据是指某些网站为了辨别用户身份,储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。
通俗来讲就是指缓存数据,包括用户名、密码、注册账户、手机号等公民个人信息
3.1 设计思想
超市会员卡
特点:
-
会员卡保存会员信息由超市生成并提供
-
会员卡由顾客保存
-
会员卡一般都会有有效期
-
超市根据会员卡分辨识别用户
服务端生成包含用户信息的Cookie(键值对字符串),返回客户端。客户端再发起请求时,会自动携带Cookie到服务端,服务端可以获取Cookie,读取到用户信息从而识别用户。
特点:
-
Cookie由服务端生成
-
Cookie有client(浏览器)保存
-
Cookie
都会有有效期
-
服务端根据cookie分辨识别用户
3.2 技术细节
Cookie的使用,我们主要关注2点:服务端如何创建Cookie,以及如何从请求中获取Cookie?
Cookie有效期的设置:
/*Cookie有效期,默认等同于浏览器。(浏览器关闭,Cookie销毁)可以通过cookie.setMaxAge(存活时长)设置其有效期
*/ck.setMaxAge(60*60*24*7);//单位秒
手动添加Cookie
//手动设置CookieCookie cookie = new Cookie("classId","202");Cookie cookie2 = new Cookie("school",URLEncoder.encode("郑大", "UTF-8"));cookie2.setMaxAge(60*60);response.addCookie(cookie);response.addCookie(cookie2);//获取Cookie Cookie[] cookies = request.getCookies();PrintWriter out = response.getWriter();out.println("<html><body>");out.println("<h1> 账户: "+ name +" <br/> 密码:"+ password +" </h1>");for(Cookie cookie : cookies){String value = URLDecoder.decode(cookie.getValue(), "UTF-8");out.println("<h2> Cookie: "+ cookie.getName() +" <br/> 值:"+ value +" </h2>");}out.println("</body></html>");
Cookie的不足:
-
只能保存字符串数据
-
不能直接保存中文字符(tomcat8.5之后可以直接保存)
-
Cookie保存数据量有限,最多4K
-
Cookie不安全
Cookie的最佳实践:使用Cookie保存少量的不重要的数据,比如:浏览记录,用户名
4.HttpSession
HttpSession会话,表示一个浏览器和服务端的多次交互过程。一个浏览器短时间内连续访问服务端始终对应着同一个HttpSession对象.
4.1设计思想
HttpSession对象就好像生活中宾馆的一个房间。一个住客在一个宾馆中居住的日子里始终居住在同一个房间。
特点:
-
房间由宾馆分配
-
房间由宾馆管理
-
每一个房间都会有使用时限
-
宾馆根据房间和住客的对应关系分辨识别住客
HttpSession对象是由服务端创建的对象,占据服务器的一小块内存空间
。一个浏览器(好比住客)多次访问服务端(好比宾馆)始终对应着同1个Session对象。服务端可以根据Session对象分别不同用户。
特点:
-
session由服务端创建
-
session保存在服务端,会占用服务器内存空间
-
session都会有默认的存活时长:距上一次访问30分钟
-
服务端根据session分辨识别用户,session和浏览器是一一对应的关系。
4.2 技术细节
HttpSession的创建和获取
无论何时获取Session,代码都是:req.getSession(); 如果是第1次获取服务器会新建一个Session,如果之前获取过则直接返回Session。
设置session
/*** 使用session共享数据*/
@WebServlet(name = "s1", value = "/s1")
public class SessionDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {//使用session共享数据//1.获取sessionHttpSession session = req.getSession();//2.存储数据session.setAttribute("name", "苍老师");}}
获取session
@WebServlet(name = "s2", value = "/s2")
public class SessionDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {//使用session获取数据//1.获取sessionHttpSession session = req.getSession();//2.获取数据Object msg = session.getAttribute("name");System.out.println(msg);}
4.3 HttpSession作用域对象的使用
HttpSession本身还可以保存、获取数据,也就是可以当做作用域对象使用。因为同1个浏览器的多次请求获取到的是同1个Session,也就可以借助Session作用域在一个浏览器的多次请求间传递数据.
request和session作用范围:
-
request作用域的范围:在一次请求中
-
session的作用域范围:在一个浏览器的多次请求间
4.4 session存活时长的设置
session默认存活时长:距上一次访问30分钟
1. 修改tomcat/conf/web.xml :作用于整个tomcat中所有的应用
<session-config><!-- 单位:分钟 --><session-timeout>30</session-timeout>
</session-config>
2.修改当前web应用的web.xml: 作用于当前web应用
<session-config><!-- 单位:分钟 --><session-timeout>10</session-timeout>
</session-config>
3.修改某一个session的存活时长:只作用于特定的session对象
HttpSession session = req.getSession();
session.setMaxInActiveInterval(60);//单位秒
4.5 session对象的销毁
-
自然死亡:距最近调用时间超过设置值
-
主动消亡:session.invalidate();
4.6 Session的典型应用
强制登录
LoginController
@WebServlet("/login")
public class LoginController extends HttpServlet{@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1 收参req.setCharacterEncoding("utf-8");String username = req.getParameter("username");String pwd = req.getParameter("pwd");//2 调用业务层方法//3 跳转UserService userService = new UserServiceImpl();if(userService.login(username,pwd)){HttpSession session = req.getSession();session.setAttribute("login",true);resp.sendRedirect("/servlet-day02/person/showPersons");return;}resp.sendRedirect("/servlet-day02/login.html");}
}
ShowAllPersonsController
@WebServlet("/person/showPersons")
public class ShowPersonsController extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 强制登录判断HttpSession session = req.getSession();//从作用域中获取登录标识,如果获取不到说明没有登录,则重定向到登录页面Object login = session.getAttribute("login");if(login == null){resp.sendRedirect("/servlet-day02/login.html");return;}// 1 收参(省略)//2 调用业务层方法PersonService personService = new PersonServiceImpl();List<Person> persons = personService.listPersons();//借助request作用域传递数据req.setAttribute("persons",persons);//请求转发到showPersonsViewreq.getRequestDispatcher("/person/showPersonsView").forward(req,resp);}
}
5.Session和Cookie的关系
Session和Cookie都可以用来实现跟踪用户状态,而二者是关系的:Session的实现依赖于Cookie。
Session的底层原理:
-
当client(浏览器)第1次发起请求并获取session后,服务端在服务器内部创建一个Session对象,并将该session的id以(JSESSIONID=id值)的cookie写回浏览器
-
当client(浏览器)二次请求时,会自动携带Cookie(也就是JSESSIONID),服务端根据cookie记录的id值获取相应的Session
6.Cookie与Session的区别
6.1存储位置不同
cookie:是针对每个网站的信息,保存在客户端.
session:是针对每个用户的,Session中主要保存用户的登录信息,保存在服务器端.
6.2存储数据大小不同
cookie:一个 cookie存储的数据不超过4K。
session:session存储在服务器上可以任意存储数据, 无大小限制.
6.3 生命周期不同
cookie:cookie可以主动设置生命周期。还可以通过浏览器工具清除.
session:session的生命周期是间隔的,从创建时开始计时如在30min内没有访问session,那么session生命周期就被销毁。
6.4 数据类型不同
cookie:value只能是字符串类型。
session:value是object类型。
6.5 安全性不同
cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗.
考虑到安全应当使用session。