会话技术【
cookie 与 session】
会话技术概述
什么是会话技术?
人与人聊天,叫是会话!
浏览器与服务器的会话:
打开浏览器,访问服务器,在关闭浏览器浏览器之前,这就是一次会话!
打开浏览器,
访问服务器1次,
访问服务器2次,
访问服务器n次,
只要浏览器没有关闭,这就是一次会话,且还在进行中!
什么时候会话结束?
浏览器关闭,表示会话结束!
会话技术:
Cookie 客户端的会话技术
Session 服务器端的会话技术
(session的原理是基于cookie)
2. Cookie
Cookie概述
客户端会话技术,数据可以保存在cookie中,即保存在客户端浏览器中!
保存:
1. 保存在浏览器进程中,浏览器已关闭,数据就没有了!(cookie默认)
2. 保存在浏览器的缓存文件目录下
需要设置cookie有效时间(cookie.setMaxAge(秒));
Cookie Api
response, 响应对应, 用于设置响应信息的!
response对象方法:
void addCookie(Cookie cookie) 在响应中添加一个cookie信息
response.addCookie(cookie_cn); 添加cookie 【set-cookie】
Cookie[] cs = request.getCookies(); // 获取cookie 【获取cookie信息】
设置cookie对象的相关信息常用方法:
void setMaxAge(int expiry) 设置有效时间,没有设置关闭浏览器数据就不存在
void setPath( 设置cookie的有效路径
void setDomain( 设置域名(访问哪个网站时候带cookie信息)
Cookie总结:
1. cookie 数据数存储到客户端浏览器的; 不安全!
2. 数据虽然存储到客户端浏览器,但是需要从服务器发送数据到浏览器
(设置set-cookie响应头)
3. 浏览器最多支持300个cookie,每个网站最多支持20个cookie
(限制目录,提升访问效率,减少服务器压力 )
4. cookie中数据不能有特殊符号(@)、中文
Cookie c =
new Cookie("lastAccessTime", URLEncoder.encode("", "utf-8"));
再次获取数据的时候,需要手动解码
URLDecoder.decode(s, enc);
URLEncoder.encode(s, enc); 编码
URLDecoder.decode(s, enc); 解码
Cookie 简单案例
设置cookie信息
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 创建Cookie对象
Cookie cookie_cn = new Cookie("cn", "China");
Cookie cookie_usa = new Cookie("usa", "America");
// 2. 把cookie添加到response响应中,这样cookie数据就会发送给浏览器了 【响应头: set-cookie】
// 接着,再此访问服务器,会带着cookie的数据访问服务器
response.addCookie(cookie_cn);
response.addCookie(cookie_usa);
}
获取Cookie信息
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 方式1:获取cookie信息
String str = request.getHeader("Cookie"); //cn=China; usa=America
System.out.println(str); // cn=China
// 方式2: request有提供获取cookie信息的方法
Cookie[] cs = request.getCookies(); // 请求头数据封装为一个个对象
// 先判断
if (cs != null && cs.length > 0) {
// 再遍历,得到每一个cookie对象
for (Cookie c : cs) {
String name = c.getName();
String value = c.getValue();
System.out.println(name + "=" + value);
}
}
}
Cookie 案例1:
public class CookieTimeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应数据的编码
response.setContentType("text/html;charset=UTF-8");
// write对象
PrintWriter out = response.getWriter();
// 0. 先从cookie中获取上次访问的时间
// 从请求中获取访问的所有cookie
Cookie[] cs = request.getCookies();
if (cs != null && cs.length >0) {
for (Cookie cookie : cs) {
// 获取保存到cookie中的key 【cn=China; usa=America】
String key = cookie.getName();
// 判断
if ("lastAccessTime".equals(key)) {
// 获取值
String value = cookie.getValue();
// 输出
out.write("上次访问时间是: " + value + "
");
");
break;
}
}
}
// 1. 获取当前时间,输出到浏览器
String date = new Date().toLocaleString();
out.write("当前时间:" + date);
// 2. 保存当前时间到cookie中 (再次访问,这个时间就是上次访问时间)
Cookie c = new Cookie("lastAccessTime", date);
// 设置有效目录
c.setPath("/day10");
// 设置有效时间
c.setMaxAge(300);
// 设置到response对象中, 通过response对象发送给浏览器cookie信息
response.addCookie(c);
}
}
Cookie 案例2:
public class GoodServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
// 一. 查询所有的商品
GoodDao dao = new GoodDao();
List list = dao.getAll();
// 通过resposne对象,向浏览器输出数据
out.write("编号 商品名称 价格 折扣价");
out.write(" 操作
");
");
for (Good g : list) {
out.write(g.getId() + " ");
out.write(g.getGoodName() + " ");
out.write(g.getPrice() + " ");
out.write(g.getDisPrice() + " ");
out
.write("查看");
out.write("
");
");
}
// 四、显示历史记录
// 从cookie中获取历史记录: 1,2,3
Cookie[] cs = request.getCookies();
if (cs != null && cs.length > 0) {
// 保存从cookie中获取的历史记录的id
String historyId = "";
for (Cookie cookie : cs) {
String name = cookie.getName();
if ("historyId".equals(name)) {
historyId = cookie.getValue();
break;
}
}
// 显示商品
// a. 分割字符串, 得到每一个id
String ids[] = historyId.split(",");
if (ids != null && ids.length > 0) {
out.write("
历史记录:
");
历史记录:
");
for (int i = 0; i < ids.length; i++) {
// 获取每一个编号
int id = Integer.parseInt(ids[i]);
// 根据编号查询商品
Good good = dao.findById(id);
out.write(good.getId() + " ");
out.write(good.getGoodName() + "
");
");
}
}
}
}
}
public class GoodDetailServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
//二、显示列表商品
// 获取id
String id = request.getParameter("id");
// 根据id查询
GoodDao dao = new GoodDao();
Good g = dao.findById(Integer.parseInt(id));
// 显示商品
out.write("商品名称: " + g.getGoodName() + "
");
");
out.write("商品价格: " + g.getPrice() + "
");
");
out.write("折扣价格: " + g.getDisPrice() + "
");
");
out.write("
回到列表");
回到列表");
// 三、保存访问的历史记录到cookie中
String value = getHistoryId(request,id); //存储的是商品的编号:如 3,1,2
Cookie c = new Cookie("historyId", value);
c.setPath("/day10");
//c.setMaxAge(300);
// 发送给浏览器
response.addCookie(c);
}
// 拼接历史记录的id
private String getHistoryId(HttpServletRequest request, String id) {
// 保存历史记录
String histroy_id = "";
// 先从request中获取所有的cookie
Cookie[] cs = request.getCookies();
if (cs != null && cs.length > 0) {
for (Cookie cookie : cs) {
// 获取历史记录的cookie
String name = cookie.getName();
if ("historyId".equals(name)) {
// 有历史记录
histroy_id = cookie.getValue();
break;
}
}
}
System.out.println();
// 第一次访问, 历史记录只有当前id
if (histroy_id == "") {
return id;
}
// 如果不是第一次访问,需要把当前的id,拼接到历史记录中(histroy_id)
String[] ids = histroy_id.split(","); // 获取历史记录中的所有id
// 创建集合,保存数组中数据
LinkedList list = new LinkedList();
// 把数组中数据拷贝到list集合
for (int i=0;i
list.add(ids[i]);
}
// 拼接历史记录
if (ids.length < 3) {
// 如果历史记录不够3个,就直接添加到集合第一个元素
list.addFirst(id);
} else {
// 判断: 当当前查看的编号在历史记录中存在, 就删除当前id,再把id添加到集合第一个元素
if (list.contains(id)){
list.remove(id);
list.addFirst(id);
} else {
list.removeLast(); // 先删除最后
list.addFirst(id); // 在把当前编号添加到集合的第一个元素中
}
}
// 处理集合数据,最终得到"1,2,3" 编号
StringBuffer sb = new StringBuffer();
for (int i=0;i
sb.append(list.get(i) + ",");
}
// 去掉最后的逗号
String result = sb.substring(0,sb.length()-1);
return result;
}
}
3. Session
Session概述
Session 表示会话对象; 服务器的会话对象!
HttpSession getSession() 从request对象中可以获取Session对象!
如何存储用户的数据?
用户输入
用户名(XX)、密码---》
登陆---》
后台验证:….. ----》 (数据如何保存?request? ServletContext?)
首页index.jsp
欢迎你,XX!
解决:
用户的数据,存储:
request: 整个项目都要用转发,不可能! (小)
ServletContext: 用户名都存储到Servletcontext中,极易被覆盖! (大)
最终,
Session: 会话对象,可以保存用户的数据! (中)
范围:
打开浏览器,访问服务器,多次访问服务器,用的是一个会话!
SessionAPI
获取session:
request.getSession(); 第一次执行时候创建session对象;
如果浏览器没有关闭,再次访问,就获取session
request.getSession(true); 同上
request.getSession(false); 不创建session,会获取已经创建的session; 如果之前
没有创建session,就返回null
域对象:
request.setAttribute(key,value);
request.getAttribute(key);
request.removeAttribute(key);
域对象总结:
域对象范围由小到大:
Request < session < servletContext
存储购物列表、登陆用户? - session
思考:
服务器,如何区分当前的多个访问是否是同一个session?
(session原理)
1. 服务器在第一次执行request.getSession() 创建session对象
a. 服务器生成一个唯一的sessionId;
b. 服务器存储id
c. 把id通过response对象发送给浏览器
(设置set-cookie相应头)
Set-Cookie:JSESSIONID=5A15565F22803450A0E60D08F229EC03; Path=/day10
2. 浏览器没有关闭,再次访问,会带着cookie头,访问服务器
Cookie:JSESSIONID=AF91F6C7CC978A1D0520F7D76BC49455
3. 服务器获取浏览器带过来的sessionId, 且获取服务器生成的id
如果相等,说明是同一个session!
总结:
Session存储基于cookie技术!
其他
int getMaxInactiveInterval() ; 获取session的最大活跃时间
void setMaxInactiveInterval(int interval) 设置sesison的最大活跃时间
建议使用配置的方式修改最大活跃时间
关于活跃时间:
Session的最大活跃时间默认为30分钟!
活跃时间:只有在活跃时间范围内使用,就会从新计算,再使用指定的默认时间!
查看session最大活跃时间的默认设置:
Tomcat/conf/web.xml
30 分钟
如果修改:
/tomcat/webapps/day10/WEB-INF/web.xml
如果在自己的项目中进行了修改,会覆盖服务器默认的配置!
如何解决浏览器关闭,session中数据丢失问题?
方案:
手动设置set-cookie的有效时间!
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取session
// Set-Cookie:JSESSIONID=0AC179863C7421C181E8677E56D5F9EA; Path=/day10
HttpSession session = request.getSession();
// 获取sessionid, 作为相应头的值
String id = session.getId();
// 创建cookie
Cookie cookie = new Cookie("JSESSIONID", id);
cookie.setPath("/day10");
cookie.setMaxAge(300); // 设置有效时间(5分钟)
// 设置响应的cookie对象
response.addCookie(cookie);
// 往session域(会话域)中保存数据
session.setAttribute("userInfo", "Jie.Yuan");
}
问题:
1. 浏览器关闭后,session有没有销毁!
浏览器关闭后,session不一定销毁!
如果关闭时候,刚好达到最大活跃时间,就销毁!
2. session什么时候销毁?
情况1: 达到最大活跃时间的时候,服务器会销毁session!
调用void invalidate() 销毁session!
情况2:手动调用: void invalidate()
“注销”
session.removeAttribute("");
session.invalidate();
会话技术为什么产生,有哪些应用?
会话技术是保存当前用户与浏览器的通讯的数据的!
应用:保存当前登陆用户、保存当前用户购买的所有商品!
如果想获取转发后的数据,用request域
request.setAttribute(..);
如果想获取重定向后的数据,用session域
session.setAttribute(..);
1. cookie 会用, 结合http协议!
2. session要回用
session.setAttribute(..);
(与cookie有关、设置的数据在什么情况可以获取?)
3. session原理
服务器如何区分不同的用户(不同的session) ?
(结合cookie)
4. cookie 练习
5. session
a. 登陆(读取xml)
b. 登陆后,显示列表
c. 列表查看
d. 显示历史记录(cookie)
e. 列表商品,添加到购买集合中,再在浏览器显示购买的集合