文章目录
Cookie和Session
一、概念
Cookie: http请求header中的一个属性。
Cookie是浏览器持久化存储数据的一种机制。网页无法访问主机的文件系统,要想存储数据就需要通过Cookie来实现。Cookie中保存的数据,也是键值对的格式(用户自定义的)最终还是要把这些键值对发送回服务器。服务器要使用Cookie来完成一些业务逻辑。
- 有些情况会使用Cookie存储当前用户的身份信息。(相当于就诊卡)
每个用户都有产生一份这样的数据,这些数据会被存储在服务器的数据库中。在服务器代码的逻辑展开执行的过程中,这些数据就会从数据库查询出来,先临时的保存在某个内存结构当中,后续如果有修改之类的操作。就会修改内存,重新写入数据库。
这个内存结构,就称作“会话"(session)
Cookie:是客户端存储数据的机制
Session:是服务器临时存储数据的机制(不算持续化存储,持续化存储是数据库完成的)
两者会相互配合使用。
在Cookie中存储的用户身份标识,也经常会理解成sessionId
每个用户都有一个自己的Session,也有不同的sessionId.
服务器会存储很多的Session,因此拿着cookie中的sessionId,就可以找到用户对应的Session
服务器会通过类似于hash表这样的键值对结构,来存储session。sessionId就是key,Session本身就是value。在Session里面存储用户自身的各种信息(同样的自定义的)。
- 通过Cookie中的sessionid,来查询到对应的Session对象,从而得到用户的具体信息。
可以通过Servlet的API来完成上述的操作。Cookie是浏览器的机制,Servlet提供了API来获取到Cookie。Session是服务器的机制,Servlet内部已经实现好了,也提供了API来方便进行使用。
二、核心方法
HttpServletRequest 类中的相关方法:
1.Cookie[ ] getCookies()方法
- 返回一个Cookie对象的数组,拿到请求中所有cookie内容。每个cookie都是一个键值对,获取到所有键值对。
2.HttpSession getSession()方法
- 这个方法能够完成:从cookie中获取sessionid,并且查询出对应session的过程。返回一个HttpSession对象
Servlet中通过HttpSession这个类来表示一个会话,服务器上有很多个会话。存在一个类似于HashMap< String,HttpSession>的结构。String是sessionid、HttpSession是Session对象。
-
如果sessionid没有从Hash表上查到,这个方法也能自动创建一个键值对(分配新的sessionid,创建一个新的HttpSession对象)
-
给登录场景来使用
HttpSession session = req.getSession(true);
//根据当前请求的cookie当中的sessionId来查询服务器的hash表,找到对应的Session对象。
//当参数为true时,如果cookie中没有sessionId(首次登录时),或者sessionId没有找到对应的Session对象。就可以创建出一个session对象
//把创建好的sessionId和Session对象存进hash表,并把sessionId设置到响应中(会在响应报头加上Set-Cookie字段),传回浏览器,让浏览器使用cookie保存
HttpServletResponse 类中的相关方法:
3.addCookie( Cookie cookie)
- 服务器要想给浏览器返回一个Cookie,把Cookie添加到响应中
HttpSession类中的方法
- 一个 HttpSession 对象里面包含多个键值对
4.getAttribute()和setAttribute()
- set设置session对象中的键值对
//通过Attribute,可以在会话中保存一些自定义的数据
session.setAttribute("username",username);
//Attribute也是键值对,存储的内容都是自定义的。这里的数据存储好后,后续跳转到其他页面,也随时可以把这个数据从会话中取出来实现一个数据在在多个Servlet之间共享。
//Attribute是会话级别的,每个用户都有自己的数据,相互不会干扰
Cookie类中的方法
-
HTTP 的 Cooke 字段中存储的实际上是多组键值对. 每个键值对在 Servlet 中都对应了一个 Cookie 对象.
-
每个cookie对象就是一个键值对
三、实现用户登录
1.实现思路:
1.登录页面(html)
- 发起一个get请求,来触发登录逻辑
2.通过Servlet处理登录的请求
- 读取用户名和密码,并且验证是否登录成功
- 如果登录成功,就会给当前用户创建一个会话,并且把得到sessionid,通过Cookie返回给客户端,客户端就会保存Cookie
3.网站主页
- 通过另一个Servlet生成的动态页面。把用户数据显示在页面上。
2.登录页面:
预期发送的请求
POST login
Content-Type:application/x-www-form-urlencoded
//使用form表单,用这个格式
//如果使用json,就需要通过ajax来构造
username=zhangsan&password=123
//预计发送的数据格式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录</title>
</head>
<body>
<!-- 使用form表单来实现登录 -->
<form action="login" method="post">
<input type="text" name="username">
<input type="text" name="passward">
<input type="submit" value="登录">
</form>
</body>
</html>
3.Servlet处理请求
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.读取请求传来的参数(用户名和密码 )
req.setCharacterEncoding("utf8");
//先给请求设置一下字符集,否则如果username是中文,getParameter获取到的可能是乱码
String username = req.getParameter("username");
String password = req.getParameter("password");
//2.验证用户名和密码是否正确,
if (!"张三".equals(username)||!"123".equals(password)){
//这种写法,避免空值的情况。equals内部能够针对为null的参数做好处理。
//登录失败,给用户返回提示
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前的用户名或者密码错误");
return;
}
//3.登录成功后,给用户创建一个会话
HttpSession session = req.getSession(true);
//根据当前请求的cookie当中的sessionId来查询服务器的hash表,找到对应的Session对象。
//当参数为true时,如果cookie中没有sessionId(首次登录时),或者sessionId没有找到对应的Session对象。就可以创建出一个session对象
//把创建好的sessionId和Session对象存进hash表,并把sessionId设置到响应中(会在响应报头加上Set-Cookie字段),传回浏览器,让浏览器使用cookie保存
//通过Attribute,可以在会话中保存一些自定义的数据
session.setAttribute("username",username);
//Attribute也是键值对,存储的内容都是自定义的。这里的数据存储好后,后续跳转到其他页面,也随时可以把这个数据从会话中取出来实现一个数据在在多个Servlet之间共享。
//Attribute是会话级别的,每个用户都有自己的数据,相互不会干扰
session.setAttribute("loginTime",System.currentTimeMillis());
//4.此时登录成功后,让页面跳转到网站首页
resp.sendRedirect("index");
//重定向跳转到index页面上(后续写一个servlet生成这个页面)
}
}
index页面
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取到当前用户对应的会话对象。生成的页面要根据当前的用户信息来构造。
HttpSession session = req.getSession(false);
//拿着之前响应返回给浏览器cookie的sessionId来查询Session对象
if (session==null){
//sessionId不存在,或者sessionId没有在hash表中查到
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前尚未登录");
return;
}
//2.从会话中拿到之前存储的用户信息
String username = (String) session.getAttribute("username");
Long loginTime = (Long) session.getAttribute("loginTime");
//3.生成一个页面,把上述数据显示到页面上
resp.setContentType("text/html;charset=utf8");
String respBody = "欢迎你 "+username+"!"+" 上次登录的时间是:"+loginTime;
resp.getWriter().write(respBody);
}
}
- 浏览器首次访问登录操作的时候,就会在服务器这边验证身份。
- 验证通过,就会创建会话
- 服务器就会保存会话信息(按照Hash表)客户端保存身份标识(sessionId)。后续浏览器访问这个网站上的其他页面都会带上cookie(sessionId)。服务器不需要让浏览器重新登陆,也能识别出浏览器的用户身份信息。