会话及其会话技术
会话概述
在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。Web 应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)与 Web服务器之间连续发生的一系列请求和响应过程,例如,一个用户在某网站上的整个购物过程就是一个会话。
在打电话过程中,通话双方会有通话内容,同样,在客户端与服务器端交互的过程中,也会产生一些数据。例如,用户甲和乙分别登录了购物网站,甲购买了一个 Nokia 手机,乙购买了一个iPad,当这两个用户结账时,Web 服务器需要对用户甲和乙的信息分别进行保存。在前面章节讲解的对象中,HttpServletRequest 对象和 ServletContext 对象都可以对数据进行保存,但是这两个对象都不可行,具体原因如下。
(1)客户端请求 Web 服务器时,针对每次 HTTP 请求,Web 服务器都会创建一个HttpServletRequest 对象,该对象只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求中的数据将会丢失。
( 2)使用 ServietContext 对象保存数据时,由于同一个 Web 应用共享的是同一个ServletContext 对象,因此,当用户在发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中所有用户购买的商品进行结算,这显然也是不可行的。为了保存会话过程中产生的数据,在 Servilet 技术中,提供了两个用于保存会话数据的对象,分别Cookie 和 Session.关于 Cookie 和 Session 的相关知识,将在下面的小节进行详细讲解。
cookie对象
cookie是一种会话技术,它用于将会话过程中的数据保存到用户的浏览器中,从而使浏览器和服务器可以更好的进行数据交换。
什么是cookie
在现实生活中,当顾客在购物时,商城经常会赠送顾客一张会员卡,卡上记录用户的个人信息(姓名、手机号等)消费额度和积分额度等。顾客一旦接受了会员卡,以后每次光临该商场时,都可以使用这张会员卡,商场也将根据会员卡上的消费记录计算会员的优惠额度和累加积分。在 Web 应用中,Cookie 的功能类似于这张会卡,当用户通过浏览器访问 Web服务器时,服务器会给客户端发送一些信息,这些信息都保存在 Cookie 中。这样,当该浏览器再次访问服务器时,都会在请求头中将 Cookie 发送给服务器,方便服务器对浏览器做出正确的响应。
服务器向客户端发送 Cookie 时,会在HTTP 响应头字段中增加 Set-Cookie 响应头字段。set-cookie头字段中设置的cookie遵循一定的语法格式。
cookie API
为了封装cookie信息,在servlet api中提供了一个javax.servlet.http.cookie类,该类包含了生存cookie信息和提取cookie信息各个属性的方法,cookie的构造方法和常用方法,具体如下。
构造方法
在cookie的构造方法中,参数name用于指定cookie的名称。value用于指定cookie的值,需要注意的是,cookie一旦创建,它的名称,就不可能更改cookie的值可以为任何值,创建后允许被修改。
Cookie类的常用方法
通过cookie的构造方法创建cookie对象后,便可调用该类的所有方法。
1)setMaxAge (int expiry)和 getMaxAge()方法
上面的这两个方法,用于设置和返回cookie在浏览器上保持有效的秒数。如果设置的值为一个正整数时,浏览器会将cookie的信息保存在本地硬盘中从当前时间开始,在没有超过指定的秒数之前,这个Cookie 都保持有效,并且同一台计算机上运行的该浏览器都可以使用这个Cookie
信息。如果设置值为负整数时,浏览器会将 Cookie 信息保存在缓存中,当浏览器关闭时,Cookie信息会被删除。如果设置值为0 时,则表示通知浏览器立即删除这个 Cookie 信息。默认情况下,Max-Age 属性的值是-1。
2) setPath ( String uri)和 getPath()方法
上面的这两个方法是针对 Cookie 的 Path属性的。如果创建的某个Cookie 对象没有设置 Path属性,那么该 Cookie 只对当前访问路径所属的目录及其子目录有效。如果想让某个 Cookie 项对站点的所有目录下的访问路径都有效,应调用Cookie 对象的 setPath()方法将其 Path 属性设置为“/”。
3)setDomain (String pattern)和 getDomain()方法
上面的这两个方法是针对cookie的domain属性的,domain鼠先生用来指定浏览器访问的域。例如,传智播客的域为“itcast.cn”。那么,当设置domain属性时,其值必须以“.”开头,如domain=. itcast.cn。默认情况下,domain属性的值为当前主机名,浏览器在访问当前主机下的资源时,都会将cookie信息回送给服务器,需要注意的是domain属性的值是不区分大小写的。
显示用户上次访问时间
创建servlet
1.创建 Servlet
在 Eclipse 中新建 Web 项目 chapter05,并在该项目下新建一个名称为cn.itcast.chapier05. cookie. example的包,在该包中编写一个名称为LastAccesSenvet的 Sepvet类,该类主要用于实现获取 Cookie 信息并将当前时间作为 Cookie 值发送给客户端。
2.配置映射信息,查看运行效果
session对象
什么是session
当人们去医院就诊时,就诊病人需要办理医院的就诊卡,该卡上只有卡号,而没有其他信息。但病人每次去该医院就诊时,只要出示就诊卡,医务人员便可根据卡号查询到病人的就诊信息。Session技术就好比医院发放给病人的就医卡和医院为每个病人保留病例档案的过程。当浏览器访
问 Web 服务器时,Servlet 容器就会创建一个 Session 对象和 ID 属性,其中,Session 对象就相当于病历档案,ID 就相当于就诊卡号。当客户端后续访问服务器时,只要将标识号传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之对应的 Session 对象为其服务。需要注意的是,由于客户端需要接收、记录和回送 Session 对象的ID,因此,通常情况下,Session 是借助 Cookie 技术来传递 ID 属性的。为了使读者更好地理解 Session,接下来,以网站购物为例,通过一张图来描述 Session 保存用户信息的原理,用户甲和乙都调用 buyServlet 将商品添加到购物车中,调用 payServlet进行
商品结算。由于甲和乙购买商品的过程类似,在此,以用户甲为例进行详细说明。当用户甲访问购物网站时,服务器为甲创建了一个 Session 对象(相当于购物车)。当甲将 Nokia 手机添加到购物车时,Nokia 手机的信息便存放到了 Session 对象中。同时,服务器将 Session 对象的 ID属性以 Cookie (Set-Cookie:JSESSIONID=111)的形式返回给甲的浏览器。当甲完成购物进行结账时,需要向服务器发送结账请求,这时,浏览器自动在请求消息头中将 Cookie (Cookie:JSESSIONID=111)信息回送给服务器,服务器根据 ID 属性找到为用户甲所创建的 Session 对象,并将session对象中所存放的nok ia手机信息取出进行结算。
实现购物车
1.创建封装图书信息类
在 chapte05 项目下新建一个名称为 cn.icast.chapter05.session.example01的包,在该包中创建一个名称为 Book 的类,该类用于封装图书的信息,其中定义了 id 和 name 属性,分别用来表示书的编号和名称。
2.创建数据库模拟类
在 cn.itcast.chapter05.session包中创建一个名称为 BookDB 的类,该类用于模
拟保存所有图书的数据库。
3.创建 Servlet
(1)创建一个名称为 ListBookServet的 Seviet 类,该 Senvet用于显示所有可购买图书的列表,通过单击“购买”链接,便可将指定的图书添加到购物车中。
(2)创建一个名称为 PunchaseSerwet的 Senlet类。
(3)创建一个名称为 CanSerlet 的 Sevlet类,该类主要用于展示用户已经购买的图书列表。
代码及成果展示
package cn.itcast.chapter05.cookie;
import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class example
*/
@WebServlet("/example")
public class example extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String time =String.format("%tF%<tF",new Date());
Cookie cookies=new Cookie("lastAcess",time);
Cookie cookies2=new Cookie("dashuju2005","2020080605045");
response.addCookie(cookies);
response.addCookie(cookies2);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
package cn.itcast.chapter05.cookie;
import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class LastAcess
*/
@WebServlet("/LastAcess")
public class LastAcess extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
Cookie[] cookies=request.getCookies();
String lasttime=null;
for(int i=0;cookies!=null && i<cookies.length;i++) {
String name=cookies[i].getName();
if("lastAccess".equals(name)) {
lasttime=cookies[i].getValue();
}
}
if(lasttime==null) {
response.getWriter().println("第一次访问网站");
}else {
response.getWriter().println("你上次访问的时间是:"+lasttime);
}
String time =String.format("%tF%<tF",new Date());
Cookie cookie=new Cookie("lastAcess",time);
response.addCookie(cookie);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
package cn.itcast.chapter05.session;
public class Book {
private String id;
private String name;
public Book() {
}
public Book(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;
}
}
package cn.itcast.chapter05.session;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
public class BookDB {
private static Map<String,Book> map = new LinkedHashMap<String,Book>();
static{
map.put("1", new Book("1","javaWeb"));
map.put("2", new Book("2","jdbc入门"));
map.put("3", new Book("3","java基础"));
map.put("4", new Book("4","struts框架"));
map.put("5", new Book("5","hibernate框架"));
}
//1.得到所有图书
public static Collection<Book> getAll(){
return map.values();
}
//2.根据map的key,也就是图书的id,得到某本图书
public static Book getBook(String id){
return map.get(id);
}
package cn.itcast.chapter05.session;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
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;
/**
* Servlet implementation class CartServlet
*/
@WebServlet("/cart")
public class CartServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CartServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
List<Book> cart=null;
HttpSession session = request.getSession(false);
boolean cartflag=true;
if(session==null) {
cartflag=false;
}else {
cart = (List<Book>) session.getAttribute("cart");
if(cart==null) {
cartflag=false;
}
}
if(!cartflag) {
out.print("对不起,请前往购买图书");
}else {
out.print("购买图书如下:"+"<br/>");
for(Book b:cart) {
out.print("购买图书:"+b.getName()+"<br/><br/>");
}
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
package cn.itcast.chapter05.session;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ListBookServlet
*/
@WebServlet("/list")
public class ListBookServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ListBookServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
Collection<Book> books = BookDB.getAll();
PrintWriter out = response.getWriter();
out.print("2020080605045+袁雪华"+"<br/>");
out.print("本网站");
for(Book b:books) {
String name = b.getName();
String id = b.getId();
String url="<a href='purcharse?id="+id+"'>点击购买</a>";
out.print("图书名称:"+name+" "+url+"<br/><br/>");
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
package cn.itcast.chapter05.session;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class PucharseServlet
*/
@WebServlet("/purcharse")
public class PucharseServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public PucharseServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String id = request.getParameter("id");
if(id==null) {
response.sendRedirect("/chapter05/list");
return;
}
Book book = BookDB.getBook(id);
//用session来实现购物车
HttpSession session = request.getSession();
List<Book> list = (List<Book>) session.getAttribute("cart");
if(list==null) {
list = new ArrayList<Book>();
session.setAttribute("cart", list);
}
//不是第一次来添加id
list.add(book);
//返回前端
Cookie cookie = new Cookie("JESSIONID",session.getId());
response.addCookie(cookie);
//跳转最后一个页面,展示
response.sendRedirect("/chapter05/cart");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}