案例:记录用户的上次访问的时间
需求:
当用户访问某些Web应用时,经常回显示出该用户上一次的访问时间,例如,QQ会显示上次的登录时间。
相关知识点
会话
一个客户但(浏览器)与Web服务器之间连续发生的一系列请求和响应过程,例如,一个用户在某网站上的整个购物过程就是一次会话。
HttpServletRequest和Httpresponse对象和ServletContext对象都可以对数据进行保存,但无法保存会话相关的数据!
- HttpServlet存储的寿命只能是一次请求,而不是一系列的请求和响应,即将请求放到request作用域中,多次请求不能共享数据。
- ServletContext对象保存数据时,同一个Web共享同一个ServletContext对象,因此无法区分不同的用户产生的会话。
cookie和session都是为了弥补http协议的无状态特性,对server端来说无法知道两次http请求是否来自同一个用户,利用cookie和session就可以让用户只登录一次,server就知道某个请求是否需用重新登录。
- Cookie:用户第一次访问服务器,服务器会在响应消息中增加Set-Cookie头字段,将用户信息以Cookie的形式发送浏览器。浏览器将其保存在浏览器缓冲区,并且后续访问服务器都会将信息以Cookie的形式发送给Web服务器。使服务器分辨是哪个用户。cookie是保存在客户端的有大小和个数的限制,不安全。
- Session:是用来存储或代表不同用户的不同信息的,而且Session一般也是存储在Cookie中,session是存在服务器,无大小和个数的限制,更加安全,session依赖于cookie。
Cookie
当用户通过浏览器访问Web服务器时,服务器会给客户端发送一些信息,这些信息会保存在Set-Cookie中,服务器会在response中返回Set-Cookie时,浏览器将其保存在Cookie中。这样,该浏览器再次访问服务器时,都会在请求头中将Cookie发送给服务器,方便服务器对浏览器做出正确的响应。
- Cookie和浏览器有什么区别?
- 浏览器可以缓存缓存任意内容,浏览器的缓存是为了避免同一页面需要多次请求而设计的,主要是为了提高用户体验和速度考虑的。
- cookie只缓存服务器需要浏览器缓存的数据。因为HTTP协议是无状态的,服务器无法记录用户上一次的操作,这样就造成了交互上的阻碍。而服务器借由从Cookie中读取包含的信息,借以维护用户和服务器会话中的状态。
Set-Cookie头字段中设置的Cookie遵循一定的语法格式:
Set-Cookie:user=itcast; Path=/;
Cookie必须以键值对的形式存在,user表示Cookie的名称,Path表示Cookie的属性,属性可以有多个,但属性之间必须用分号;和空格分隔。
Cookie在浏览器和服务器之间的传输过程
Cookie的基本使用
创建cookie:new Cookie(name,value)
将cookie发送给浏览器:HttpServletResponse.addCookie()
接收浏览器携带的所有cookie: HttpServletRequest.getCookies()
案例实现
流程分析
步骤分析
- 获得从客户端带过来的所有Cookie
- 从所有的Cookie中查找名称的Cookie
- 判断是否是第一次访问?是的话显示欢迎:否的话显示上次访问时间
- 记录当前的时间,并且利用Cookie将时间回写到浏览器端。
代码实现
public class LastAccessTimeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得当前时间
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String currentTime = format.format(date);
//1.创建Cookie 记录当前的最新访问时间
Cookie cookie = new Cookie("lastAccessTime",currentTime);
cookie.setMaxAge(60*10*500);//设置保存cookie时间
response.addCookie(cookie);
//2.获得客户端携带cookie-----lastAccessTime
String lastAccessTime =null;
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for(Cookie coo:cookies){
if("lastAccessTime".equals(coo.getName())){
lastAccessTime = coo.getValue();
}
}
}
response.setContentType("text/html;charset=UTF-8");
if(lastAccessTime==null){
response.getWriter().write("您是第一次访问");
}else{
response.getWriter().write("您上一次的访问时间是:"+lastAccessTime);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Cookie的总结
- 会话级别的Cookie:默认的,关闭了浏览器Cookie就销毁了
- 持久级别的Cookie:需要设置有效市场的,关闭浏览器也不会销毁Cookie
- setMaxAge(int expiry);以秒为单位的时间,超过了该时间,超过了改时间后Cookie会自动销毁,setMaxAge(0);手动删除持久性的Cookie。
- setPath(String uri);设置Cookie的有效途径
- 1)cookie.setPath("/day16/demo");表示day16项目下demo子目录下所有的servlet,都可以访问当前cookie。但“/day16"或"/day16/aaa"将不能访问
- 2)cookie.setPath("/day16"); 表示day16项目下的所有servlet都可以访问当前的cookie
- 3)cookie.setPath("/");表示tomcat下的所有web项目均可以当问当前的cookie
- cookie唯一表示:
-
唯一标识:domain+path+name(类似java中 包+类名)
- domain 域名,不同的网站使用的是不同的域名,cookie就不同。
- path 路径,通过cookie.setPath()设置的内容
- name cookie名称,通过new Cookie(name,…)确定的内容。
-
例如如下表示的是两个cookie,可以同时存在
- /web/a/b/CookieName
- /web/a/CookieName
-
如果路径和名称一样,两次addCookie()后者将覆盖前者。
-
Cookie的API
Session
HTTP的传输还有个问题,即明文传输。而且HTTP请求容易被篡改。又根据客户端信息不可靠原则,我们需要一个东西来验证用户的身份——Session。Session也可以做到Cookie的部分功能,但Session是保存在服务器上的。服务端的信息无法随便篡改,所以Session更加可靠。具体的做法一般是服务端和客户端之间不传输明文数据,而是传输一段经过特殊加密的密文,密文对应的服务器硬盘数据中才是真实的数据。这段数据根据不同的ID属性,在Session激活后从服务器磁盘中取出到内存中,再返回给浏览器。
Session的使用
相关api
//获取Session对象
request.getSession()//相当于boolean设置为true
request.getSession(boolean create)//true时,不存在session则创建,false不存在时返回null
//获取SessionId
getId()
//获取当前session对象的创建时间
getCreationTime()
//获取最后一次访问该session对象的时间
getLastAccessedTime()
//设置Session最大时效
setMaxInactiveInterval()
//获取Session最大时效
getMaxInactiveInterval()
//判断当前Session对象是不是新建的
/**
如果客户端请求消息中返回了一个与Servlet程序当前获得的HttpSession对象的会话标识号相同的会话标识号,则认为这个HttpSession对象不是新建的。
*/
isNew()
//销毁当前Session对象
invalidate()
//属性相关
setAttribute()
getAttribute()
removeAttribute()
getAttributeNames()
实例
public class SessionServlet1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* request.getSession()方法内部会判断 该客户端是否在服务器端已经存在session
* 若存在,则直接返回该session
* 若不存在,创建一个session对象并返回
*/
//创建属于该客户端会话的私有的session区域
HttpSession session = request.getSession();
session.setAttribute("name", "gua");
String id = session.getId();
//手动创建一个存储JSESSIONID的Cookie 为该cookie设置持久化时间
Cookie cookie = new Cookie("JSESSIONID",id);
cookie.setPath("/WEB16/");
cookie.setMaxAge(60*10);
response.addCookie(cookie);
response.getWriter().write("JSESSION:"+id);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
作用域总结
- ServletContext:针对一个WEB应用。一个WEB应用只有一个ServletContext对象,使用该对象保存的数据在整个WEB应用中都有效
- 创建:服务器启动的时候
- 销毁:服务器关闭的时候或者项目移除
- HttpSession:针对一次会话,使用该对象保存数据 ,一次会话(多次请求)内数据有效。
- 创建:服务器第一次调用getSession()的时候,服务器创建session的对象
- 销毁:
- 1.非正常关闭服务器(正常关闭:session被序列化)
- 2.Session过期了,默认时间是30分钟
- 3.手动调用session的invalidate的方法
- HttpServletRequest:针对一次请求。使用该对象保存数据,一次请求(即一个页面或转发的多个页面)内数据有效
+ 创建:客户端向服务器发送一次请求
+ 销毁:服务器为这次请求作出响应之后,销毁request - 三个作用域对象操作的API相同
- 存放数据:setAttribute(name,value)
- 获得数据:getAttribute(name)
- 删除数据:removeAttribute(name)