什么是会话呢?
从浏览器第一次访问服务器(Tomcat) 开始一直到 浏览器关闭为止,这一整套的流程。称之为一次会话。
效果图
会话技术是什么?有哪些呢?
会话技术: 就是在 一次会话当中,需要使用到的技术点,主要可以完成数据的存储和数据的共享。 会话技术的分类: (1) 客户端的会话技术: cookie 存储到浏览器当中 (2) 服务端的会话技术: session 存储到服务器会话域当中
Cookie 的快速入门
操作步骤
1. 创建 Cookie 的对象,创建对象的过程当中,可以进行值的存放。 Cookie c = new Cookie(String类型的键, String类型的值); 2. 发送 Cookie 给浏览器 response.addCookie(c); 3. 下次获取 Cookie 的数据值 Cookie[] cookieArray = request.getCookies();
案例代码
/***
* Cookie的快速入门
*
* http://localhost:8080/JavaWebDay17/CookieDoor01Servlet
*/
@WebServlet("/CookieDoor01Servlet")
public class CookieDoor01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("CookieDoor01Servlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("CookieDoor01Servlet.doPost");
//【1】创建 Cookie 的对象
Cookie c = new Cookie("message","helloCookie");
//【2】发送Cookie到浏览器当中
resp.addCookie(c);
}
}
/***
* Cookie的快速入门
*
* http://localhost:8080/JavaWebDay17/CookieDoor02Servlet
*/
@WebServlet("/CookieDoor02Servlet")
public class CookieDoor02Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("CookieDoor02Servlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("CookieDoor02Servlet.doPost");
//【3】获取到客户端的 cookie 信息
Cookie[] cookeArray = req.getCookies();
//遍历数组
for (Cookie c : cookeArray) {
String name = c.getName();
if (name!=null && name.equals("message")){
//获取到值
String value = c.getValue();
System.out.println(name+","+value);
}
}
}
}
校验执行过程:
第一次访问
1. 我们 可不可以发送多个 Cookie 数据呢? 2. Cookie 可以在浏览器当中保存多长时间呢? 3. Cookie 能不能存储中文或者特殊字符? 4. Cookie 能不能进行不同情况下共享使用?
问题1:我们 可不可以发送多个 Cookie 数据呢?
回答:
可以发送多个 Cookie 数据。 那么怎么发送呢? 创建多次的 Cookie 对象,发送多次就可以了。 Cookie c1 = new Cookie("name","zhangsan"); Cookie c2 = new Cookie("age","23"); response.addCookie(c1); response.addCookie(c2);
问题2:Cookie 可以在浏览器当中保存多长时间呢?
回答:
默认情况下,我们的 Cookie 随着浏览器的关闭,会话结束了,Cookie 也会消失,这种我们叫做 "临时Cookie" 如何设置 Cookie 的有效期呢? 可以去采用 setMaxAge(int) 定义Cookie 的有效期。 参数信息 int 取值不同,有效期也不相同。 1. 如果参数是 正数, 则表示 有效期是多少秒。 (单位是秒) c.setMaxAge(30) 表示可以存活30秒 2. 如果参数是 负数, 则表示 默认情况, 关闭浏览器, cookie 直接消失 3. 如果参数是 零, 则表示 清除Cookie数据
问题3:Cookie 能不能存储中文或者特殊字符?
回答:
中文: 在Tomcat8之前是 不可以存储到 Cookie 当中的, 在Tomcat8之后是 可以存储到 Cookie 当中。 特殊字符: 在 Cookie 里面是不可以存储的 问题: 如果我们一定要存储 中文或者特殊字符,应该怎么办呢? 解决方案,采用 编码转换。转换编码存储,拿到数据之后,解码。 URL编码: URLEncoder.encode("需要编码的字符串","编码方式UTF-8"); URL解码: URLDecoder.decode("需要解码的字符串","编码方式UTF-8");
问题4:Cookie 能不能进行不同情况下共享使用?
回答:
1. 共享一: 我们发布的 第一个 JavaWeb 模块的代码在 Tomcat 服务器上面, 我们再次发布 另一个 JavaWeb 模块代码在 Tomcat 服务器上面, 两者的 Cookie 可以实现共享吗? 默认情况下是不可以实现共享的。 问题是:如果想要实现共享应该怎么办呢? 需要采用方法提升 Cookie 的作用范围。 setPath("/") 这里的斜杠指的是虚拟路径 2. 共享二: 我们发布的 JavaWeb 项目代码 在 不同的 Tomcat 服务器上面,可不可以实现共享呢? 默认情况下是不可以实现共享的。 问题是: 如果两个 tomcat 服务器上面的 Cookie 想要实现共享,怎么办? 举例: xueshu.baidu.com 学术 news.baidu.com 新闻 tieba.baidu.com 贴吧 其中 .baidu.com 称之为 一级域名。 xueshu、news、tieba 称之为 二级域名。 如果我们给 cookie 的范围设置为 一级域名的级别,则二级域名的内容,可以实现 Cookie 共享 存在方法: setDomain(".baidu.com"); 设置之后,二级域名就可以访问共享 Cookie了
1. Cookie 是存在于 客户端浏览器当中的。 2. 在浏览器当中,对于单个 Cookie 而言,有大小限制,最大为 4KB (说明:不同浏览器限制不相同) 3. 在浏览器当中,对于同一个域名下面的 Cookie 而言,有数量的限制,最多20个(说明:不同浏览器数目限制不同)
1. 存储少量非敏感的数据。 2. 在不登录的情况下,可以实现浏览器对客户的识别。 例如: 偏好设置。 在百度当中,搜索引擎的做偏好设置。
效果图
备注:如果采用登录,永久性保存,则将偏好设置保存到 服务器的数据库上面。
如果没有登录,临时存储,会保存到 Cookie 当中
说明
在我们访问一个 Servlet 的时候,如果是第一次访问,则显示 "您好,首次访问" 如果不是第一次访问,则显示 "欢迎回来,您的上次访问时间是 2088年9月2日15:19:48"
分析
/***
* 案例: 最后一次的访问时间。
*
* 地址: http://localhost:8080/JavaWebDay17/LastServlet
*/
@WebServlet("/LastServlet")
public class LastServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 直接查找 cookie 是否存在
Cookie c = findCookieByName("lasttime", req);
//2. 分情况考虑问题了
String message;
if (c == null){
message = "您好,首次访问";
}else{
String value = c.getValue();
message = "欢迎你" + URLDecoder.decode(value,"UTF-8");
}
//3. 展示数据
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println(message);
//4. 需要将数据保存到 cookie 当中
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String timeStr = sdf.format(new Date());
timeStr = URLEncoder.encode(timeStr,"UTF-8");
Cookie timeCookie = new Cookie("lasttime",timeStr);
//添加一个过时时间,有效期 30天
timeCookie.setMaxAge(60*60*24*30);
resp.addCookie(timeCookie);
}
//定义一个方法,专门用于查找是否存在指定name的 cookie数据
protected Cookie findCookieByName(String name, HttpServletRequest req) throws ServletException, IOException {
//获取到所有的 Cookie 信息
Cookie[] cookies = req.getCookies();
//定义Cookie 是否找到
Cookie c = null;
//判断当前的 cookies 没有数据直接返回, 或者 传入的名称直接是 null
if (cookies == null || name == null){
return c;
}
//表示 cookies 数组当中存在数据
for (Cookie child : cookies) {
//判断 name 是否在 数组的元素 name 当中,如果在,则赋值
if (name.equals(child.getName())){
c = child;
break;
}
}
return c;
}
}
1. 应用域 ServletContext 2. 会话域 Session 3. 请求域 Request 4. 页面域 PageContext
四个域对象,都存在三个方法
1. 存值 void setAttribute(String,Object) 2. 取值 Object getAttribute(String) 3. 删除值 void removeAttribute(String)
/***
* Session 会话域的快速入门
*
* 网址: http://localhost:8080/JavaWebDay17/SessionDoor1Servlet
*/
@WebServlet("/SessionDoor1Servlet")
public class SessionDoor1Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("SessionDoor1Servlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("SessionDoor1Servlet.doPost");
//获取到会话域对象 session
HttpSession session = req.getSession();
//存值的操作
session.setAttribute("name","zhangsan");
//-----------
//如果采用的是请求域
req.setAttribute("pass","666666");
}
}
/***
* Session 会话域的快速入门
*
* 网址: http://localhost:8080/JavaWebDay17/SessionDoor2Servlet
*/
@WebServlet("/SessionDoor2Servlet")
public class SessionDoor2Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("SessionDoor2Servlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("SessionDoor2Servlet.doPost");
//获取到会话域对象 session
HttpSession session = req.getSession();
//获取值
Object name = session.getAttribute("name");
System.out.println("name = " + name);
//--------------
//如果采用的是请求域
Object pass = req.getAttribute("pass");
System.out.println("pass = " + pass);
}
}
小结: session 的实现是 基于 Cookie 的
1. 当客户端浏览器关闭之后,服务器不关闭,再次启动客户端浏览器,获取到Session 是不是同一个? 2. 客户端不关闭,服务器关闭,再次启动服务器,获取到 Session 是不是同一个? 3. Session 失效的时间是什么?
问题1:当客户端浏览器关闭之后,服务器不关闭,再次启动客户端浏览器,获取到Session 是不是同一个?
回答:
不是同一个。 验证方式: 直接打印输出 session 对象,展示地址值,就可以看到效果。 问题: 不是同一个,但是会存在影响,两次的 session 对象不同,如果需求是 必须相同,应该怎么办呢? 解决: cookie 存在有效期,当浏览器关闭之后,会持续的保存着。有一段有效期。 方法是 cookie.setMaxAge(60*60*24) 设置为1天的时间
案例代码
/***
* 路径: http://localhost:8080/JavaWebDay17/SessionDemo01Servlet
*/
@WebServlet("/SessionDemo01Servlet")
public class SessionDemo01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("SessionDemo01Servlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("SessionDemo01Servlet.doPost");
//直接获取到 Session 的对象
HttpSession session = req.getSession();
//---------------------------
//定义一个 Cookie 用于保存 Session 的id信息
Cookie c = new Cookie("JSESSIONID",session.getId());
//设置有效期, 设置为1小时
c.setMaxAge(60*60);
//发送 cookie 到客户端浏览器里面保存
resp.addCookie(c);
//---------------------------
//直接打印输出 session 展示地址值
System.out.println("session = " + session);
}
}