动态网站开发讲课笔记09:会话及会话技术——Session对象
一、什么是Session
- 目标:了解什么是Session
1、Session对象
- 当人们去医院就诊时,就诊病人需要办理医院的就诊卡,就诊卡上只有卡号,没有其他信息。但病人每次去该医院就诊时,只要出示就诊卡,医务人员便可根据卡号查询到病人的就诊信息。Session技术类似医院办理就诊卡和医院为每个病人保留病历档案的过程。当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性, Session对象就相当于病历档案,ID就相当于就诊卡号。当客户端后续访问服务器时,只要将ID传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之对应的Session对象为其服务。
2、Session的优点
- Session还具有更高的安全性,它将关键数据保存在服务器。cookie则是将数据存在客户端的浏览器中。因此cookie是较为危险的,若客户端遭遇黑客攻击,cookie信息容易被窃取,数据也可能被篡改,而运用Session可以有效避免这种情况的发生。
二、了解HTTPSession API
- 目标:掌握HttpSession接口中的常用方法
1、Session对象的getSession()方法
- Session是与每个请求消息紧密相关的,为此,HttpServletRequest定义了用于获取Session对象的getSession()方法,该方法有两种重载形式。
方法 | 说明 |
---|---|
public HttpSession getSession(boolean create) | 根据传递的参数判断是否创建新的HttpSession对象,如果参数为true,则在相关的HttpSession对象不存在时创建并返回新的HttpSession对象,否则不创建新的HttpSession对象,而是返回null。 |
public HttpSession getSession() | 相当于第一个方法参数为true时的情况,在相关的HttpSession对象不存在时总是创建新的HttpSession对象。需要注意的是,由于getSession()方法可能会产生发送会话标识号的Cookie头字段,所以必须在发送任何响应内容之前调用getSession()方法。 |
2、HttpSession接口中的常用方法
方法声明 | 功能描述 |
---|---|
String getId() | 用于返回与当前HttpSession对象关联的会话标识号 |
long getCreationTime() | 用于返回Session创建的时间,这个时间是创建Session的时间与1970年1月1日00:00:00之间时间差的毫秒表示形式 |
long getLastAccessedTime() | 用于返回客户端最后一次发送与Session相关请求的时间,这个时间是发送请求的时间与1970年1月1日00:00:00之间时间差的毫秒表示形式 |
void setMaxInactiveInterval(int interval) | 用于设置当前HttpSession对象可空闲的以秒为单位的最长时间,也就是修改当前会话的默认超时间隔 |
boolean isNew() | 判断当前HttpSession对象是否是新创建的 |
void invalidate() | 用于强制使Session对象无效 |
ServletContext getServletContext() | 用于返回当前HttpSession对象所属于的Web应用程序对象,即代表当前Web应用程序的ServletContext对象 |
void setAttribite(String name, Object value) | 用于将一个对象与一个名称关联后存储到当前的HttpSession对象中 |
String getAttribute() | 用于从当前HttpSession对象中返回指定名称的属性对象 |
void removeAttribute(String name) | 用于从当前HttpSession对象中删除指定名称的属性 |
三、 Session的生命周期
- 目标:掌握Session对象的生效与失效
1、Session生效
- Sessinon在用户第一次访问服务器时创建,需要注意只有访问JSP、Servlet等程序时才会创建Session。此外,还可调用request.getSession(true)强制生成Session。只访问HTML、IMAGE等静态资源并不会创建Session。
2、Session失效
(1)“超时限制”判断Session是否生效
- Web服务器采用“超时限制”判断客户端是否还在继续访问。在一定时间内,如果某个客户端一直没有请求访问,那么,Web服务器就会认为该客户端已经结束请求,并且将与该客户端会话所对应的HttpSession对象变成垃圾对象,等待垃圾收集器将其从内存中彻底清除。反之,如果浏览器超时后,再次向服务器发出请求访问,那么,Web服务器会创建一个新的HttpSession对象,并为其分配一个新的ID属性。
(2)强制Session失效
- 使用invalidate()方法可以强制使Session对象失效
HttpSession session = request.getSession();
session.invalidate(); // 注销该request的所有session
四、Session案例演示 - 实现购物车
1、创建Web项目
-
创建Java Enterprise项目,添加Web Application
-
设置项目名称与保存位置
2、修改Artifact名称,重新部署项目
-
在项目结构窗口里修改Artifact名称
-
修改首页,启动服务器,查看结果
3、创建蛋糕实体类
- 创建net.hdl.session.bean包,然后在包里创建Cake类
package net.hdl.session.bean;
/**
* 功能:蛋糕实体类
* 作者:胡德兰
* 日期:2023年04月14日
*/
public class Cake {
private static final long serialVersionUID = 1L;
private String id;
private String name;
public Cake() {
}
public Cake(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cake{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
- 创建net.hdl.session.test包,然后在包里创建TestCake类
package net.hdl.session.test;
import net.hdl.session.bean.Cake;
/**
* 功能:测试蛋糕实体类
* 作者:胡德兰
* 日期:2023年05月23日
*/
public class TestCake {
public static void main(String[] args) {
// 1. 基于无参构造方法创建蛋糕对象
Cake cake1 = new Cake();
// 设置蛋糕对象属性
cake1.setId("001");
cake1.setName("金玫瑰蛋糕");
// 打印蛋糕对象
System.out.println(cake1);
// 2. 基于有参构造方法创建蛋糕对象
Cake cake2 = new Cake("002", "黄苹果蛋糕");
// 打印蛋糕对象
System.out.println(cake2);
}
}
- 运行程序,查看结果
4、创建蛋糕数据库模拟类
- 在net.hdl.session根包里创建dao包,然后在子包里创建CakeDao类,用于模拟访问蛋糕数据库
package net.hdl.session.dao;
import net.hdl.session.bean.Cake;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 功能:蛋糕数据访问对象
* 作者:胡德兰
* 日期:2023年04月14日
*/
public class CakeDao {
private static Map<String, Cake> cakes = new LinkedHashMap<String, Cake>();
static {
cakes.put("1", new Cake("1", "A类蛋糕"));
cakes.put("2", new Cake("2", "B类蛋糕"));
cakes.put("3", new Cake("3", "C类蛋糕"));
cakes.put("4", new Cake("4", "D类蛋糕"));
cakes.put("5", new Cake("5", "E类蛋糕"));
}
// 获得所有蛋糕
public static Collection<Cake> findAllCakes() {
return cakes.values();
}
// 按编号获取蛋糕
public static Cake findCakeById(String id) {
return cakes.get(id);
}
}
- 在net.hdl.session.test包里创建TestCakeDao类
package net.hdl.session.test;
import net.hdl.session.bean.Cake;
import net.hdl.session.dao.CakeDao;
import java.util.Collection;
/**
* 功能:测试蛋糕用户访问对象
* 作者:胡德兰
* 日期:2023年05月23日
*/
public class TestCakeDao {
public static void main(String[] args) {
// 查询全部蛋糕
Collection<Cake> cakes = CakeDao.findAllCakes();
// 通过增强for循环遍历蛋糕集合
for (Cake cake : cakes) {
System.out.println(cake.getId() + "\t" + cake.getName());
}
System.out.println();
// 按编号查询蛋糕
String id = "4";
Cake cake = CakeDao.findCakeById(id);
// 输出蛋糕对象属性
System.out.println(cake.getId() + "\t" + cake.getName());
}
}
- 运行程序,查看结果
5、创建蛋糕列表处理程序
- 创建net.hdl.session.servlet包,然后在包里创建CakeListServlet类,用于显示所有可购买蛋糕的列表,通过单击“购买”链接,便可将指定的蛋糕添加到购物车中
package net.hdl.session.servlet;
import net.hdl.session.bean.Cake;
import net.hdl.session.dao.CakeDao;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.util.Collection;
/**
* 功能:显示蛋糕列表
* 作者:胡德兰
* 日期:2023年05月23日
*/
@WebServlet(name = "CakeListServlet", urlPatterns = "/cake_list")
public class CakeListServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html; charset=utf-8");
// 获取字符输出流
PrintWriter out = response.getWriter();
// 获取蛋糕集合
Collection<Cake> cakes = CakeDao.findAllCakes();
out.print("<body style='text-align: center'>");
out.print("<h3>本站提供的蛋糕</h3>");
// 显示全部蛋糕
for (Cake cake : cakes) {
String url = "purchase?id=" + cake.getId();
out.print(cake.getId() + " " + cake.getName()
+ " <a href='" + url + "'>点击购买</a><br>");
}
out.print("</body>");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
- 运行程序,查看结果
6、创建购物处理程序
- 在net.hdl.session.servlet包里创建PurchaseServlet类
package net.hdl.session.servlet;
import net.hdl.session.bean.Cake;
import net.hdl.session.dao.CakeDao;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 功能:购物处理程序
* 作者: 胡德兰
* 日期: 2023年04月21 日
*/
@WebServlet(name = "PurchaseServlet",urlPatterns = "/purchase")
public class PurchaseServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取用户是否购买蛋糕的id
String id=request.getParameter("id");
//判断用户是否选购
if(id!=null){
//按照id获取蛋糕对象
Cake cake= CakeDao.findCakeById(id);
//创建或获取用户的Session对象
HttpSession session=request.getSession();
//从Session对象中获取用户的购物车
List<Cake> cart=(List<Cake>) session.getAttribute("cart");
//判断购物车是否为空
if(cart==null){
//为用户创建一个购物车(LIST集合模拟购物车)
cart=new ArrayList<>();
//将购物车存入Session对象
session.setAttribute("cart",cart);
}
//将选购的蛋糕放入购物车
cart.add(cake);
//创建Cookie用来保存Session的标识号
Cookie cookie=new Cookie("JSESSIONID",session.getId());
//设置cookie属性
cookie.setMaxAge(30*60);//30分钟
cookie.setPath("/Servlet");
//加入cookie
response.addCookie(cookie);
//从定向到购物车页面(CartSerclet,其中uel为'cart')
response.sendRedirect("cart");
}else {
//从定向到蛋糕列表显示页面(CakeListServlet,其url为'cakr_list')
response.sendRedirect("cake_list");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
}
7、创建购物车处理程序
- 在net.hdl.session.servlet包里创建CartServlet类
package net.hdl.session.servlet;
import net.hdl.session.bean.Cake;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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;
import java.util.List;
/**
* 功能:
* 作者:胡德兰
* 日期:2023年04月14日
*/
@WebServlet(name = "CartServlet", urlPatterns = "/cart")
public class CartServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html; charset=utf-8");
// 获取字符输出流
PrintWriter out = response.getWriter();
// 变量cart引用用户的购物车
List<Cake> cart = null;
// 变量hasPurchased标记用户是否买过商品
boolean hasPurchased = true;
// 获得用户的session
HttpSession session = request.getSession(false);
// 判断会话是否为空
if (session == null) { // 尚未购买过商品
hasPurchased = false;
} else {
// 获得用户购物车
cart = (List) session.getAttribute("cart");
// 判断购物车是否为空
if (cart == null) { // 尚未购买过商品
hasPurchased = false;
}
}
out.print("<body style='text-align: center'>");
// 判断用户是否购买过商品
if (!hasPurchased) {
out.print("遗憾,您尚未购买任何商品~<br>");
} else {
// 显示用户购买蛋糕的信息
out.print("<h3>您购买的蛋糕</h3>");
for (Cake cake : cart) {
out.print(cake.getId() + " " + cake.getName() + "<br>");
}
}
out.print("</body>");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
8、启动服务器,查看结果
上一篇: 动态网站开发03:H
下一篇: 动态网站开发02:J