JavaWeb学习笔记-Cookie、Session
什么是会话技术?
会话介绍
会话:浏览器与服务器之间的多次的请求与响应。
为了实现一些功能,浏览器与服务器可能会进行多次的请求与响应,从浏览器访问服务器开始,到访问服务器结束(关闭浏览器、到了过期时间)。这期间产生了多次的请求与响应加在一起称之为浏览器与服务器的一次会话。
会话过程中产生的一些数据,可以通过会话技术(Cookie 与 Session)进行保存。
会话作用
什么时候会用到会话管理呢?最常见的就是购物车,当我们登录成功后,把商品加入到购物车之中,此时我们无论再浏览什么商品,当点击购物车时,那些加入的商品都仍在购物车中。
在我们的实际开发中,还有很多地方都离不开会话管理技术。比如,我们在论坛发帖,没有登录的游客身份是不允许发帖的。所以当我们登录成功后,无论我们进入哪个版块发帖,只要权限允许的情况下,服务器都会认识我们,从而让我们发帖,因为登录成功的信息一直保留在服务器端的会话中。
通过上面的两个例子,我们可以看出,它是为我们共享数据用的,并且是在不同请求间实现数据共享。也就是说,如果我们需要在多次请求间实现数据共享,就可以考虑使用会话管理技术了。
会话分类
在JavaEE的项目中,会话管理分为两类。分别是:客户端会话管理技术(Cookie)和服务端会话管理技术(Session)。
客户端会话管理技术(Cookie)
它是把要共享的数据保存到了客户端。每次请求时,把会话信息带到服务器,从而实现多次请求的数据共享。
服务端会话管理技术(Session)
它本质仍是采用客户端会话管理技术,只不过保存到客户端的是一个特殊的标识,并且把要共享的数据保存到了服务端的内存对象中。每次请求时,把这个标识带到服务器端,然后使用这个标识,找到对应的内存空间,从而实现数据共享。
客户端会话管理技术(Cookie)
Cookie概述
Cookie把要共享的数据保存到了客户端,每次请求时,把会话信息带到服务器端,从而实现多次请求的数据共享!
作用
它可以保存客户浏览器访问网站的相关内容(需要客户端不禁用Cookie)。从而在每次访问需要同一个内容时,先从本地缓存获取,使资源共享,提高效率。
浏览器通过HTTP请求的消息头,将Cookie带回给服务器端;通过HttpServletRequest.getCookies()获取到所有的Cookie对象,再根据name的属性来确定时哪一个Cookie。
Cookie的API
Cookie的属性
| 属性名称 | 属性作用 | 是否重要 |
|---|---|---|
| name | cookie的名称 | 必要属性 |
| value | cookie的值(不能是中文) | 必要属性 |
| path | cookie的路径 | 重要 |
| domain | cookie的域名 | 重要 |
| maxAge | cookie的生存时间。 | 重要 |
| version | cookie的版本号。 | 不重要 |
| comment | cookie的说明。 | 不重要 |
我们可以看看Cookie类是怎么写的:

和表格里的东西基本上是一一对应的。
Cookie的常用方法
Cookie类中没有提供空参的构造方法!只提供了一个参数为name和value的构造方法。
/**
* 通过指定的名称和值构造一个Cookie
*
* Cookie的名称必须遵循RFC 2109规范。这就意味着,它只能包含ASCII字母数字字符,
* 不能包含逗号、分号或空格或以$字符开头。
* 创建后无法更改cookie的名称。
*
* 该值可以是服务器选择发送的任何内容。
* 它的价值可能只有服务器才感兴趣。
* 创建之后,可以使用setValue方法更改cookie的值。
*/
public Cookie(String name, String value) {
validation.validate(name);
this.name = name;
this.value = value;
}
Cookie的添加与获取

添加
/**
* 添加Cookie到响应中。此方法可以多次调用,用以添加多个Cookie。
*/
public void addCookie(Cookie cookie);
响应
/**
* 这是HttpServletRequest中的方法。
* 它返回一个Cookie的数组,包含客户端随此请求发送的所有Cookie对象。
* 如果没有符合规则的cookie,则此方法返回null。
*/
public Cookie[] getCookies();
Cookie的使用
案例描述如下:
需求说明
创建一个Cookie,设置Cookie的path,通过不同的路径访问,从而查看请求携带Cookie的情况。
实现步骤
- 通过响应对象写出一个提示信息
- 创建Cookie对象,指定name和value
- 设置Cookie的最大存活时间
- 通过响应对象将Cookie添加到客户端
- 通过请求对象获取Cookie对象
- 将Cookie对象中的访问时间写出
web.xml
<?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>ServletDemo01</servlet-name>
<servlet-class>com.servlet.ServletDemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo01</servlet-name>
<url-pattern>/ServletDemo01</url-pattern>
</servlet-mapping>
</web-app>
ServletDemo01
package com.servlet;
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;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ServletDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.通过响应对象写出一个提示信息
// 解决中文乱码问题
resp.setContentType("text/html;charset=UTF-8");
PrintWriter pw = resp.getWriter();
pw.write("欢迎访问本网站,您的最后访问时间为:<br>");
// 2.创建Cookie对象,指定name和value
Cookie cookie = new Cookie("time",System.currentTimeMillis()+"");
// 3.设置Cookie的最大存活时间 1小时
cookie.setMaxAge(3600);
// 4.通过响应对象将Cookie添加到客户端
resp.addCookie(cookie);
// 5.通过请求对象获取Cookie对象
Cookie[] arr = req.getCookies();
for (Cookie c : arr) {
// 判断当前的Cookie是不是自己想要的
if("time".equals(c.getName())){
// 6.将Cookie对象中的访问时间写出
String value = c.getValue();
// 使用SimpleDateFormat将其格式化为时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
pw.write(sdf.format(new Date(Long.parseLong(value))));
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
运行结果

请求消息头Handers

Cookie的细节

Cookie访问路径限制
取自第一次访问的资源路径的前缀,
只要以这个前缀开头(包括子级路径)就可以获取到!
反之就获取不到!
例如:
/servlet/ServletDemo01 中创建了cookie
然而在 /servlet/ServletDemo02 or /servlet/aaa/ServletDemo03 路径中都是可以获取到的!
但是在 /bbb/ServletDemo04 中就获取不到!
服务端会话管理概述(Session)
我们真正要使用的就是HttpSession
HttpSession概述
HttpSession的本质也是采用客户端会话管理技术。
只不过保存到客户端的是一个特殊的标识,并且把要共享的数据保存到了服务端的内存对象中。每次请求时,把这个标识带到服务器端,然后使用这个标识,找到对应的内存空间,从而实现数据共享。
HttpSession是Servlet规范中的四大域对象之一的会话对象。
四大域对象
| 域对象名称 | 范围 | 级别 | 备注 |
|---|---|---|---|
| PageContext | 页面范围 | 最小,只能在当前页面用 | 因范围太小,开发中用的很少 |
| ServletRequest | 请求范围 | 一次请求或当期请求转发用 | 当请求转发之后,再次转发时请求域丢失 |
| HttpSession | 会话范围 | 多次请求数据共享时使用 | 多次请求共享数据,但不同的客户端不能共享 |
| ServletContext | 应用范围 | 最大,整个应用都可以使用 | 尽量少用,如果对数据有修改需要做同步处理 |
它是Servlet规范中提供的一个接口。我们使用的是Tomcat服务器,它对Servlet规范进行了实现,所以HttpSession接口的实现由Tomcat提供。
HttpSession的中的常用方法

HttpSession的获取
HttpSession实现类对象需要通过HttpServletRequest来获取。
HttpServletRequest有一个getSession()的方法

获取流程

注意:
request.getSession(带参数):参数是boolean类型的,表示当没有找到指定Session后是否自动创建。
- true是自动创建——也是默认的
- false不是自动创建的——request.getSession(false); 没有找到就返回null。
HttpSession的使用
需求
在请求HttpSessionDemo1这个Servlet时,携带用户名信息,并且把信息保存到会话域中,然后从HttpSessionDemo2这个Servlet中获取登录信息。
步骤
- 在第一个Servlet中获取请求的用户名
- 获取HttpSession对象
- 将用户名设置到共享数据中
- 在第二个Servlet中获取HttpSession对象
- 获取共享数据的用户名
- 将获取到的用户名响应给客户端浏览器。
在ServletDemo01中创建了Session
使用的URL : localhost:8080/ServletDemo01?username=lisi
@WebServlet("/ServletDemo01")
public class ServletDemo01 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求的用户名
String username = req.getParameter("username");
//2.获取HttpSession的对象
HttpSession session = req.getSession();
System.out.println(session);
System.out.println(session.getId());
//3.将用户名信息添加到共享数据中
session.setAttribute("username",username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
在ServletDemo02中查看Session
使用URL:localhost:8080/ServletDemo02
@WebServlet("/ServletDemo02")
public class ServletDemo02 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取HttpSession对象 多态
HttpSession session = req.getSession();
System.out.println(session);
System.out.println(session.getId());
//2.获取共享数据
Object username = session.getAttribute("username");
//3.将数据响应给浏览器
resp.getWriter().write(username+"");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
在网页就可以看到打印出的Session。

浙公网安备 33010602011771号