前言
了解Cookie和Session技术。
一、Cookie
1、什么是Cookie
Cookie主要用于存储键值对。Cookie技术是服务器通知客户端保存键值对(Cookie对象)的一种技术。保存好键值对后,每次发送请求附带Cookie对象发送给服务器,每个Cookie对象的大小不能超过4kb。
public Cookie(String name, String value) {
validation.validate(name);
this.name = name;
this.value = value;
}
2、创建并添加Cookie对象
A.Step
B.XML configuration
<?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_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieServlet</servlet-name>
<servlet-class>com.xhu.servlet.CookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieServlet</servlet-name>
<url-pattern>/cookieServlet</url-pattern>
</servlet-mapping>
</web-app>
C.通过反射分流
package com.xhu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* 所有Servlet都会对请求分流,所以抽象出来
*/
public abstract class BaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
/**
* @param req
* @param resp
* @throws ServletException
* @throws IOException
* @function 通过反射实现动态分流
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String action = req.getParameter("action");
try {
Method declaredMethod = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
declaredMethod.setAccessible(true);
declaredMethod.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
D.Code
package com.xhu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CookieServlet extends BaseServlet {
/**
* 创建cookie并通知浏览器将cookie存储到本地
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.创建cookie对象
Cookie c1 = new Cookie("username", "root");
Cookie c2 = new Cookie("password", "root");
//2.设置response编码以及浏览器的解码格式
resp.setContentType("text/html;charset=utf-8");
//3.通知浏览器本地存cookie
resp.addCookie(c1);
resp.addCookie(c2);
//4.创建成功
resp.getWriter().print("Cookie对象创建成功");
}
}
E.Result
3、如何获取Cookie对象
A.Step
B.Code
protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取所有Cookie对象
Cookie[] cookies = req.getCookies();
//2.打印Cookie对象
PrintWriter writer = resp.getWriter();
for (int i = 0; i < cookies.length; i++) {
writer.print(cookies[i].getName() + ":" + cookies[i].getValue());
writer.println();
}
}
C.Result
D.CookieUtil之寻找Cookie对象
package com.xhu.utils;
import javax.servlet.http.Cookie;
public class CookieUtil {
public static Cookie findCookie(String name, Cookie[] cookies) {
if (name == null || cookies == null || cookies.length == 0)
return null;
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName()))
return cookie;
}
return null;
}
}
4、如何修改Cookie对象值
A.方案
1)方案一
服务端生成新的同名不同值Cookie对象,然后把其添加在响应头中,浏览器会自动根据响应头的set-Cookie来更新。
protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.生成同名不同值Cookie对象。
Cookie cookie = new Cookie("password", "lls");
//2.将Cookie对象添加到响应头。
resp.setContentType("text/html;charset=utf-8");
resp.addCookie(cookie);
//3.回传消息添加成功给浏览器
resp.getWriter().println("password成功修改为lls");
}
2)方案2
寻找指定Cookie对象,然后setValue,最后通知客户端。
protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.寻找指定Cookie对象
Cookie cookie = CookieUtil.findCookie("password", req.getCookies());
//2.修改Cookie对象值
cookie.setValue("root");
//3.通知客户端
resp.setContentType("text/html;charset=utf-8");
resp.addCookie(cookie);
//4.回传消息修改成功给浏览器
resp.getWriter().println("password成功修改为root");
}
B.Result
5、查看浏览器的Cookie
6、Cookie的生命控制
对Cookie对象的生命控制,指设置它的存活时间。通过setMaxAge()
来设置
A.默认-1
默认-1表示session级别,当浏览器关闭时则将Cookie对象删除。private int maxAge = -1;
protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.生成Cookie对象
Cookie cookie = new Cookie("defaultLife","defaultLife");
//2.将默认生命周期的Cookie对象回传浏览器
resp.setContentType("text/html;charset=utf-8");
resp.addCookie(cookie);
//3.通知消息
resp.getWriter().println("默认生命周期的Cookie对象创建成功");
}
B.立即删除
protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.生成Cookie对象
Cookie cookie = new Cookie("deleteNow","deleteNow");
//2。设置其生命周期为立马删除
cookie.setMaxAge(0);
//3.通知客户端
resp.setContentType("text/html;charset=utf-8");
resp.addCookie(cookie);
//3.回传消息
resp.getWriter().println("设置立马删除的Cookie对象成功");
}
C.存活1小时
protected void life3600(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.生成Cookie对象
Cookie cookie = new Cookie("life3600","life3600");
//2。设置其生命周期为一个小时后删除
cookie.setMaxAge(60 * 60);
//3.通知客户端
resp.setContentType("text/html;charset=utf-8");
resp.addCookie(cookie);
//4.回传消息
resp.getWriter().println("设置存活一小时的Cookie对象成功");
}
Result
7、Cookie的有效路径Path
当请求发起时,浏览器会把Cookie对象附带在请求头里发送给服务器,而只有请求路径能跟Cookie对象的Path匹配时才能将该Cookie对象发送给服务端。
cookieA-path | cookieB-path |
---|---|
/工程路径/cookieServlet | /工程路径/ |
Cookie对象 | 请求路径 | 能否发送 |
---|---|---|
CookieA | /工程路径 | 能 |
cookieB | /工程路径 | 能 |
cookieA | /工程路径/cookieS | 否 |
cookieB | /工程路径/cookieS | 能 |
protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.生成Cookie对象
Cookie cookie = new Cookie("path","path");
//2。设置其path路径
cookie.setPath(req.getContextPath()+"cookieS");
//3.通知客户端
resp.setContentType("text/html;charset=utf-8");
resp.addCookie(cookie);
//4.回传消息
resp.getWriter().println("path路径设置完成");
}
8、免用户名登录
A.Step
B.Code
<input class="itxt" type="text" placeholder="请输入用户名" autocomplete="off" tabindex="1"
name="username" value="${cookie.username.value}"/>
protected void login(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//获取参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//判断系统是否存在该用户
User user = us.login(username, password);
//不存在该用户
if (user == null) {
req.setAttribute("errorMsg", "用户名和密码错误");
req.setAttribute("username", username);
req.setAttribute("password", password);
req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);
return;
}
req.getSession().setAttribute("user", user);
Cookie cookie = new Cookie("username", user.getUsername());
resp.setContentType("text/html;charset=utf-8");
resp.addCookie(cookie);
req.getRequestDispatcher("pages/user/login_success.jsp").forward(req, resp);
}
二、Session
1、什么是Session
规范HttpSession,用于维护客户端与服务端一次连接过程中所需要维护的信息,如客户端与服务端连接的唯一标识id、客户端登录成功后的用户信息。session存储在服务端。
2、创建和获取Session对象
request.getSession()
获取该请求Session对象。
第一次请求则该操作是创建并获取Session对象,否则是获取当前Session对象。
1)如何判断是否为创建?request.getSession().isNew()
3、存储、获取信息
HttpSession session = request.getSession();
User user = new User("username","password");
session.setAttribute("user",user);
user = session.getAttribute("user");
4、可控Session对象的生命周期
HttpSession session = req.getSession();
//获取session超时时长
session.getMaxInactiveInterval();
//设置session超时时长为1小时,负数表示永不销毁。
session.setMaxInactiveInterval(60 * 60);
//让session马上无效
session.invalidate();
Tomcat的web.xml中配置了超时时长,如果想修改该项目中所有的session默认时长,就可以改idea整合tomcat下的web.xml
<session-config>
<session-timeout>30</session-timeout>
</session-config>
三、为什么能通过请求获取session
一旦session对象创建,则每次response都会让客户端添加cookie对象,该对象的存了session的唯一标识符id,而每次请求都会带上该cookie对象,所以服务端能根据传过来的Cookie对象中的id来找到当前连接的session对象。
总结
1)cookie存入客户端(浏览器)
2)session存入服务端(Tomcat)
3)通过Cookie对象来寻找Session对象。
参考文献
[1] JavaWeb 尚硅谷
附录
1、cookie.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cookie</title>
<base href="http://localhost:8080/cookie_sessions/">
<style type="text/css">
ul li {
list-style: none;
}
</style>
</head>
<body>
<iframe name="target" width="500" height="500" style="float: left;"></iframe>
<div style="float: left;">
<ul>
<li><a href="cookieServlet?action=createCookie" target="target">Cookie的创建</a></li>
<li><a href="cookieServlet?action=getCookie" target="target">Cookie的获取</a></li>
<li><a href="cookieServlet?action=updateCookie" target="target">Cookie值的修改</a></li>
<li>Cookie的存活周期</li>
<li>
<ul>
<li><a href="cookieServlet?action=defaultLife" target="target">Cookie的默认存活时间(会话)</a></li>
<li><a href="cookieServlet?action=deleteNow" target="target">Cookie立即删除</a></li>
<li><a href="cookieServlet?action=life3600" target="target">Cookie存活3600秒(1小时)</a></li>
</ul>
</li>
<li><a href="cookieServlet?action=testPath" target="target">Cookie的路径设置</a></li>
<li><a href="" target="target">Cookie的用户免登录练习</a></li>
</ul>
</div>
</body>
</html>
2、session.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="cache-control" content="no-cache"/>
<meta http-equiv="Expires" content="0"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Session</title>
<base href="http://localhost:8080/13_cookie_session/">
<style type="text/css">
ul li {
list-style: none;
}
</style>
</head>
<body>
<iframe name="target" width="500" height="500" style="float: left;"></iframe>
<div style="float: left;">
<ul>
<li><a href="sessionServlet?action=createOrGetSession" target="target">Session的创建和获取(id号、是否为新创建)</a></li>
<li><a href="sessionServlet?action=setAttribute" target="target">Session域数据的存储</a></li>
<li><a href="sessionServlet?action=getAttribute" target="target">Session域数据的获取</a></li>
<li>Session的存活</li>
<li>
<ul>
<li><a href="sessionServlet?action=defaultLife" target="target">Session的默认超时及配置</a></li>
<li><a href="sessionServlet?action=life3" target="target">Session3秒超时销毁</a></li>
<li><a href="sessionServlet?action=deleteNow" target="target">Session马上销毁</a></li>
</ul>
</li>
<li><a href="" target="target">浏览器和Session绑定的原理</a></li>
</ul>
</div>
</body>
</html>