一、会话
1 基本介绍
1.1 什么是会话?
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个 web 资源,然 后关闭浏览器,整个过程称之为一个会话。
1.2 会话过程中要解决的一些问题?
1) 每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会 产生一些数据 ,服
务器要想办法为 每个用户 保存这些数据
2) 例如:多个用户点击超链接通过一个 servlet 各自购买了一个商品,服务器应该想办法
把每一个用户购买的商品保存在各自的地方,以便于这些用户点结帐 servlet 时,结帐
servlet 可以得到用户各自购买的商品为用户结帐
2 会话的两种技术
Session 和 Cookie
二、Cookie
1.Cookie 有什么用
思考问题 1-抛砖引玉
大家在访问某个网站的时候,是否能看到提示你上次登录网站的时间 , 而且要注意的是不同 用户上次登录的时间肯定是不一样的,这是怎么实现的 ?
思考问题 2-抛砖引玉
大家在访问某个购物网站的时候,是否能看到提示你曾经浏览过的商品,不同用户浏览过
的商品肯定不一样,这是怎么实现的
解决之道—cookie 技术
Cookie( 小甜饼 ) 是客户端技术,服务器把每个用户的数据以 cookie 的形式写给用户各自的浏 览器。当用户使用浏览器再去访问服务器中的 web 资源时,就会带着各自的数据去。这样 web 资源处理的就是用户各自的数据了。【简单示意图】
2 cookie 介绍
2.1 二说 cookie
- Cookie 是服务器在客户端保存用户的信息,比如登录名,浏览历史等, 就可以,以 cookie方式保存
- Cookie 信息就像是小甜饼(cookie 中文)一样,数据量并不大,服务器端在需要的时候可以从客户端/浏览器读取(http 协议),可以通过图来理解
- cookie 数据是保存在浏览器的
2.2 cookie 可以用来做啥
- 保存上次登录时间等信息
- 保存用户名,密码, 在一定时间不用重新登录
- 网站的个性化,比如定制网站的服务,内容
3 cookie 基本使用
3.1 cookie 常用方法
- Cookie 有点象一张表(K-V),分两列,一个是名字,一个是值,数据类型都是 String , 如图
- 如何创建一个 Cookie(在服务端创建的)
- 如何将一个 Cookie 添加到客户端
- 如何读取 cookie(在服务器端读取到 cookie 信息)
4 cookie 底层实现机制-创建和读取 Cookie
4.1 创建
package com.hspedu.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class CreateCookie extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("CreateCookie被调用.....");//1.创建一个cookie对象//username 该cookie的名字是唯一的//linran 是该cookie的值 可以创建多个cookie//这是cookie在服务器端Cookie cookie = new Cookie("username", "linran");//2 将cookie发送到浏览器response.addCookie(cookie);response.setContentType("text/html;charset=utf-8");PrintWriter writer =response.getWriter();writer.println("<h1>创建cookie成功</h1>");writer.flush();writer.close();}
}
记得导入jar包、配置xml、配置tomcat哦
4.2 读取
package com.hspedu.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** 读取浏览器的cookie信息*/
public class ReadCookie extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("ReadCookie被调用.....");//1 通过request读取cookie对象Cookie[] cookies = request.getCookies();if(cookies!=null&&cookies.length!=0){for (Cookie cookie : cookies) {System.out.println("cookie name = "+cookie.getName()+" value = "+cookie.getValue());}}response.setContentType("text/html;charset=utf-8");//3 给浏览器返回信息PrintWriter writer = response.getWriter();writer.println("<h1>读取信息成功</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
不同会话, jsessionid 不同;
5 cookie 应用实例
5.1 读取指定 Cookie
创建工具类
package com.hspedu.cookie;import javax.servlet.http.Cookie;public class CookieUtils {//编写一个方法返回指定名字的cookie的值public static Cookie readCookieByName(String name,Cookie [] cookies){//判断传入的参数是否正确if(name==null || "".equals(name) ||cookies==null||cookies.length==0){return null;}else {//遍历cookie数组for (Cookie cookie : cookies) {if(name.equals(cookie.getName())){return cookie;}}}return null;}
}
package com.hspedu.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class ReadCookieByNameServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("ReadCookieByNameServlet被调用.....");//得到指定cookie的value//先获得浏览器携带的所有cookieCookie[] cookies = request.getCookies();//使用工具类获取指定的cookieCookie email =CookieUtils.readCookieByName("email",cookies);if(email!=null){System.out.println("cookie name = "+email.getName()+" value = "+email.getValue());}else {System.out.println("没有这个cookie");}//返回这个信息给浏览器response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<h1>完成读取cookie的信息");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
5.2 修改 Cookie
package com.hspedu.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class UpdateCookieServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("UpdateCookieServlet被调用........");//根据名字查找cookieString cookName="email";Cookie[] cookies = request.getCookies();Cookie cookie=CookieUtils.readCookieByName(cookName,cookies);if(cookie==null){System.out.println("当前访问服务端的浏览器没有该cookie");}else {cookie.setValue("newlinran@baidu.com");response.addCookie(cookie);}//遍历cookieSystem.out.println("修改后的cookie");for (Cookie cookie1 : cookies) {System.out.println("cookie name = "+cookie1.getName()+" value = "+cookie1.getValue());}response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<h1>更新任务完成</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
6 cookie 生命周期
6.1 介绍
- Cookie 的生命周期指的是如何管理 Cookie 什么时候被销毁(删除)
- setMaxAge()
6.2 应用实例
package com.hspedu.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class CookieLiveServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("CookieLiveServlet被调用");//演示创建一个cookie 生命周期为60秒Cookie cookie =new Cookie("job","java");//1 从创建该Cookie计时 60秒后无效//2 浏览器来根据创建的时间,计时到60秒,就认为该cookie无效//3 如果该cookie无效,那么浏览器在发http请求时,就不再携带该cookiecookie.setMaxAge(60);//4 将cookie保存到浏览器response.addCookie(cookie);response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<h1>设置cookie生命周期成功</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
7 cookie 有效路径
- Cookie 有效路径 Path 的设置
- Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。哪些不发。 path属性是通过请求的地址来进行有效的过滤
- 规则如下
8 作业
- 需求: 完成自动填写登录账户应用案例 , 如果用户登录成功,则下次登录自动填写登录账户(如图
- 如果用户名是 linran, 密码是 123456, 则认为该用户合法, 登录成功,否则登录失败
- 要求实现如果登录成功,则该用户,在 3 天内登录,可以自动填写其登录名
- 登录页面需要使用 servlet 返回,而不能使用 html
package com.hspedu.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class UserUiServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("UserUiServlet被调用.......");//读取cookieCookie[] cookies = request.getCookies();Cookie username_cookie = CookieUtils.readCookieByName("username", cookies);Cookie password_cookie =CookieUtils.readCookieByName("password",cookies);String username="";String password="";if(username_cookie!=null){//如果有username=username_cookie.getValue();}if(password_cookie!=null){password=password_cookie.getValue();System.out.println(password);}response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<!DOCTYPE html>\n" +"<html lang=\"en\">\n" +"<head>\n" +" <meta charset=\"UTF-8\">\n" +" <title>登录页面</title>\n" +"</head>\n" +"<body>\n" +"<h1>用户登录界面</h1>\n" +"<form action=\"/cs/loginServlet\">\n" +" u:<input type=\"text\" name=\"username\" value=\""+username+"\"><br>\n" +" p:<input type=\"password\" name=\"password\" value=\""+password+"\"><br>\n" +" <input type=\"submit\" value=\"登录\">\n" +"</form>\n" +"</body>\n" +"</html>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
package com.hspedu.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("LoginServlet被调用");//接收表单提交的用户名和密码String username = request.getParameter("username");String password = request.getParameter("password");response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();//判断是否合法if("linran".equals(username)&& "123456".equals(password)){//将登录成功的用户名和密码以cookie的形式进行保存Cookie username1 = new Cookie("username", username);//设置生命周期username1.setMaxAge(3600*24*3);Cookie password1 = new Cookie("password", password);password1.setMaxAge(3600*24*3);response.addCookie(username1);response.addCookie(password1);//合法writer.println("<h1>登录成功</h1>");}else {writer.println("<h1>登录失败</h1>");}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
9 Cookie 注意事项和细节
- 一个 Cookie 只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
- 一个 WEB 站点可以给一个浏览器发送多个 Cookie,一个浏览器也可以存储多个 WEB 站点提供的 Cookie。
- cookie 的总数量没有限制,但是每个域名的 COOKIE 数量和每个 COOKIE 的大小是有限 制的 (不同的浏览器限制不同, 知道即可) , Cookie 不适合存放数据量大的信息。
- 注意,删除 cookie 时,path 必须一致,否则不会删除
- Java servlet 中 cookie 中文乱码解决[设置编码+解码】
- 如果存放中文的 cookie, 默认报错, 可以通过 URL 编码和解码来解决, 不建议存 放中文的 cookie 信息
三、session
1. session 有什么用
- 不同的用户登录网站后,不管该用户浏览该网站的哪个页面,都可显示登录人的名字,还可以随时去查看自己的购物车中的商品, 是如何实现的?
- 也就是说,一个用户在浏览网站不同页面时,服务器是如何知道是张三在浏览这个页面,还是李四在浏览这个页面?
解决之道—session 技术, 简单说
- Session 是服务器端技术,服务器在运行时为每一个用户的浏览器创建一个其独享的session 对象/集合
- 由于 session 为各个用户浏览器独享,所以用户在访问服务器的不同页面时,可以从各自的 session 中读取/添加数据, 从而完成相应任务
2 session 基本原理
2.1 Sesson 原理示意图
- 当用户打开浏览器,访问某个网站, 操作 session 时,服务器就会在内存(在服务端)为该浏览器分配一个 session 对象,该 session 对象被这个浏览器独占, 如图
- 这个 session 对象也可看做是一个容器/集合,session 对象默认存在时间为 30min(这是在tomcat/conf/web.xml),也可修改
2.2 Session 可以做什么
- 网上商城中的购物车
- 保存登录用户的信息
- 将数据放入到 Session 中,供用户在访问不同页面时,实现跨页面访问数据
- 防止用户非法登录到某个页面
- ......
2.3 如何理解 Session
- session 存储结构示意图
- 你可以把 session 看作是一容器类似 HashMap,有两列(K-V),每一行就是 session 的一个属性。
- 每个属性包含有两个部分,一个是该属性的名字(String),另外一个是它的值(Object)
3 session 常用方法
Session 的基本使用
- 创建和获取 Session,API 一样
- 向 session 添加属性
- 从 session 得到某个属性
- 从 session 删除调某个属性:
- isNew(); 判断是不是刚创建出来的 Session
- 每个 Session 都有 1 个唯一标识 Id 值。通过 getId() 得到 Session 的会话 id 值
4 session 底层实现机制
4.1 原理分析图
4.2 代码演示
演示 Session 底层实现机制-创建和读取 Session
创建
package com.hspedu.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;public class CreatSession extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("CreatSession被调用......");//获取session 同时也可能创建SessionHttpSession session = request.getSession();//给session获取idSystem.out.println("当前sessionId= "+session.getId());//给session存放数据session.setAttribute("email","zs@qq.com");//给浏览器一个回复response.setContentType("text/html;charset=utf-8");PrintWriter writer =response.getWriter();writer.println("<h1>创建session成功</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
读取
package com.hspedu.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;public class ReadSessionServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("ReadSessionServlet被调用......");//演示读取Session//如果没有也会被创建HttpSession session = request.getSession();Object email = session.getAttribute("email");if(email!=null){System.out.println("session属性 email= "+(String) email);}else {System.out.println("session没有email属性");}//给浏览器一个回复response.setContentType("text/html;charset=utf-8");PrintWriter writer =response.getWriter();writer.println("<h1>读取session成功</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
5 session 生命周期
5.1 Session 生命周期-说明
- public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间(以秒为单位),
- 超过指定的时长,Session 就会被销毁。
- 值为正数的时候,设定 Session 的超时时长。
- 负数表示永不超时
- public int getMaxInactiveInterval()获取 Session 的超时时间
- public void invalidate() 让当前 Session 会话立即无效
- 如果没有调用 setMaxInactiveInterval() 来指定 Session 的生命时长,Tomcat 会以Session默认时长为准,Session 默认的超时为 30 分钟, 可以在 tomcat 的 web.xml 设置
- Session 的生命周期指的是 :客户端/浏览器两次请求最大间隔时长,而不是累积时长。 即当客户端访问了自己的 session,session 的生命周期将从 0 开始重新计算。(解读: 指 的是同一个会话两次请求之间的间隔时间)
- 底层: Tomcat 用一个线程来轮询会话状态,如果某个会话的空闲时间超过设定的最大值,则将该会话销毁
5.2 Session 生命周期-应用实例
创建
package com.hspedu.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;public class CreateSession2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("CreateSession2被调用.....");//创建sessionHttpSession session = request.getSession();System.out.println("CreateSession2 sid= "+session.getId());//设置生命周期session.setMaxInactiveInterval(60);//添加属性session.setAttribute("u","jack");//给浏览器一个回复response.setContentType("text/html;charset=utf-8");PrintWriter writer =response.getWriter();writer.println("<h1>创建session2成功,设置生命周期60s</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
读取
package com.hspedu.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;public class ReadSession2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("ReadSession2被调用.....");//获取sessionHttpSession session = request.getSession();System.out.println("ReadSession2 sid= "+session.getId());String res="";//读取session的属性Object u = session.getAttribute("u");if(u!=null){System.out.println("读取到session属性 u= "+(String) u);res="读取到session属性 u= "+(String) u;}else {System.out.println("读取不到session属性 u 说明原来session被销毁");res="读取不到session属性 u 说明原来session被销毁";}//给浏览器一个回复response.setContentType("text/html;charset=utf-8");PrintWriter writer =response.getWriter();writer.println("<h1>"+res+"</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
删除
package com.hspedu.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;public class DeleteSession extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("DeleteSession被调用.....");HttpSession session = request.getSession();session.invalidate();//给浏览器一个回复response.setContentType("text/html;charset=utf-8");PrintWriter writer =response.getWriter();writer.println("<h1>删除session成功</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}