背景:传统HTTP协议的服务端并不能存储任何有关用户状态的信息
会话跟踪:上次请求传递、修改的数据能够影响到下次请求,并且能识别出是相同客户端发送出来的。
一次会话的简单流程
前提:确保浏览器允许使用Cookie
数据保存位置: 客户端上 ---- 一个Cookie对应一个键值对
跟踪思想: 客户端第一次请求,服务器在返回报文上将Cookie发给客户端,客户端将Cookie信息存储在一个文件上,客户端每次请求时,便Cookie信息放在请求报文里面,服务器根据请求报文的信息从而进行比对、确认客户端身份。
注意1: 任何身份都有时效性,例如自己身份证有效期,Cookie也是一样,时效一过,只能下次请求时,服务器自动颁发一张新的身份证给你。
注意2: 客户端收到的Cookie都是 resp.addCookie (Cookie)、换句话说服务器给客户端的Cookie都需要自己写代码给客户端,而客户端Cookie会自动给服务器,客户无需任何动作
注意3: Cookie的键值对不能有空格符,非要有空格必须将其进行转码。
Cookie流程图
此是 javax.servlet.http.Cookie,不是 java.net.HttpCookie;
HttpServletRequest.getCookies() → 得到请求报文中的所有Cookies
HttpServletResponese.addCoooke( Coookie ) → 将Cookie放入回复报文上
@WebServlet(urlPatterns = {"/CookieTest.do"})
public class CookieTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie ck_name = new Cookie("name","lrc");
Cookie ck_year = new Cookie("year","18");
ck_name.setDomain("localhost"); // 满足1:域名是localhost
ck_year.setDomain("localhost");
ck_name.setPath("/"); // 满足2:地址栏 localhost/* 客户端就可以发送cookie给服务器
ck_year.setPath("/JavaWeb_learning"); // 地址栏 localhost/JavaWeb_learning/* 客户端就会发送Cookie给服务器
ck_name.setMaxAge(240); // Cookie在客户端的存活时间4分钟
ck_year.setMaxAge(240);
resp.addCookie(ck_name); // 将Cookie放置在 返回报文 给客户端
resp.addCookie(ck_year);
PrintWriter pw = resp.getWriter();
pw.write("A new Cooking is being retured to the client
");
pw.flush();
pw.close();
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
}
}
运行上述代码测试步骤
地址栏输入:http://localhost:8080/JavaWeb_learning/CookieTest.do – 生成Cookie给客户端
地址栏输入这几个地址:localhost:8080、localhost:8080/任意层级域名 – 都没有出现year这个Cookie
地址栏输入:http://localhost:8080/JavaWeb_learning – 只有匹配URL:localhost/JavaWeb_learning/* 才会将year Cookie给服务器
1. 依然使用了Cookie、不过只用Cookie的话,会把大量的状态信息存到客户端主机上,而使用Cookie-Session结合,客户端只需要存储SessionID就可以了,大量的状态信息存在服务器Session这个内存空间上,减少了HTTP请求携带大量的用户状态Cookie信息
2. 服务器只要新生成Session,则自动会将sessionID发送给客户端
3. 浏览器关闭则客户端的Cookie-SessionID自动删除,但服务器的session并没有销魂
生成HttpSession对象: HttpServletRequest.getSession()
@WebServlet (urlPatterns = {"/cookie.do"})
public class TestCookie1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 如果客户端请求中没有sessionID,服务器会自动创建一个新的session,并且将新的sessionID给客户端
req.getSession();
}
}
第三次请求 – 浏览器关闭(或者换个浏览器),打开新浏览器 → 上次的sessionID(Cookie)已经被删除,服务器重新发送新的sessionID,但服务器原来的session并没有删除
背景: 客户端禁用Cookie,导致不能存储sessionID,所以只能通过后台程序员给请求的URL进行补充sessionID,或者客户端人员自己手动在地址栏补充sessionID ---- 即增加会话标识
超链接、表单的action、重定向地址 都必须重写URL(JSP页面) ---- 静态html页面不可以动态重写
注意: 请求报文中有sessionID则使用请求中的sessionID,即使地址栏你手动拼接了另一个sessionID,则依然使用请求报文中的sessionID。
servlet代码 - TestCookie1.java
@WebServlet (urlPatterns = {"/cookie.do"})
public class TestCookie1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
HttpSession hs = req.getSession();
hs.setAttribute("sessionID", hs.getId());
hs.setAttribute("用户", "小明");
}
}
jsp代码 - TestSession.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String scheme = request.getScheme();
String server = request.getServerName();
int port = request.getServerPort();
String project = request.getContextPath();
String base = scheme + "://" + server + ":" + port + project + "/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=base%>">
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
sessionID:<%= session.getAttribute("sessionID") %>
<br>
用户名:<%= session.getAttribute("用户") %>
</body>
</html>
重定向引用的时上面的jsp页面
@WebServlet (urlPatterns = {"/cookie.do"})
public class TestCookie1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
HttpSession hs = req.getSession();
hs.setAttribute("sessionID", hs.getId());
hs.setAttribute("用户", "小明");
resp.sendRedirect("/JavaWeb_servlet/TestSession.jsp"); // ①
// String bringSessionPath = resp.encodeRedirectURL("/JavaWeb_servlet/TestSession.jsp"); // ②
// resp.sendRedirect( bringSessionPath ); // ③
}
}
运行①代码 - 请求localhost:8080/cookie.do
运行②③代码、注释①代码 - 请求localhost:8080/cookie.do
背景:浏览器禁用Cookie,可以在给客户端的每个JSP页面保存一个进行存储sessionID
hiddenForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String scheme = request.getScheme(); // http
String server = request.getServerName(); // localhost
int port = request.getServerPort(); // 8080
String project = request.getContextPath(); // /项目名
String base = scheme + "://" + server + ":" + port + project + "/"; // http://localhost:8080/homework/
%>
Insert title here
<%
HttpSession hs = request.getSession();
String sessionID = hs.getId();
hs.setAttribute("user", "小明");
hs.setAttribute("password", "123456");
%>
重定向到用户信息页面
TestCoookie1.java
@WebServlet (urlPatterns = {"/cookie.do"})
public class TestCookie1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
String sessionID = req.getParameter("sessionID");
resp.sendRedirect("/JavaWeb_servlet/message.jsp" + ";jsessionid=" + sessionID);
}
}
message.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String scheme = request.getScheme(); // http
String server = request.getServerName(); // localhost
int port = request.getServerPort(); // 8080
String project = request.getContextPath(); // /项目名
String base = scheme + "://" + server + ":" + port + project + "/"; // http://localhost:8080/homework/
%>
Insert title here
用户:<%= session.getAttribute("user")%>
密码:<%= session.getAttribute("password") %>
运行结果图: