Javaweb基础之cookie&session
来源:互联网 发布:linux 删除tomcat日志 编辑:程序博客网 时间:2024/05/17 22:26
一、会话跟踪技术概述
1.什么叫会话
会话可以理解为客户端和服务器之间的一次对话,在一次对话中可能会有多个请求和响应。
例如:用户通过浏览器登录访问qq空间,登录,查看某人的主页,查看某人详细说说,日志,相册等等,然后关闭浏览器。整个过程称之为一次会话。
在Javaweb中,客户向某一服务器发出第一个请求开始,会话就开始了,直到客户端浏览器被关闭,会话结束。
在一个会话中的多个请求中共享数据,这个就是会话跟踪技术。例如在银行系统操作中:
* 请求银行主页
* 请求登录(请求参数:用户名和密码)
* 请求转账 (具体的用户名)
* 请求信用卡还款(具体的用户)
在以上会话中,当前登录的用户信息必须在整个会话中共享,因为登录是张三,在转账和还款时一定是相对张三的账户(总不能转账完成,突然发现,我转的钱是谁的?),所以,就需要借助Cookie和Session来完成在一个会话过程中共享数据的能力。
二、Cookie
HTTP协议是无状态协议,也就是说每个请求都是独立的,无法记录前一次请求的状态,但Http协议中可以使用Cookie来完成会话跟踪,在Javaweb中,使用Session来完成会话跟踪,而session底层依赖于Cookie技术。
1.Cookie概述
在HTTP中,Cookie由一个键和一个值构成的。随着服务器的响应发送给客户端。当客户端再次访问服务器时会把Cookie再发送给服务器。
如果服务器发送重复的cookie,就会覆盖浏览器原有的cookie。
2.cookie示例1
需求:客户端访问AServlet,AServlet在响应中添加cookie,浏览器自动保存cookie,然后客户端再次访问BServlet,在BServlet获取请求中cookie。
* AServlet
(1)创建cookie对象
(2)将cookie响应给浏览器
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); //UUID,全局唯一标识符,在一台机器上生成的数字不会重复 //创建cookie //UUID.randomUUID()获取值,将该值转为字符串toString(); String val=UUID.randomUUID().toString(); //创建cookie对象 Cookie cookie=new Cookie("id",val); //将cookie响应给浏览器 response.addCookie(cookie); }
- BSservlet:获取cookie,
(1) 从request获取cookie数组,
(2) 判断该数组是否为空,遍历并根据cookie的name获取值
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); //获取了cookie Cookie[] cookie=request.getCookies(); if(cookie!=null){//如果cookie不为空 for(Cookie c:cookie){ if(c.getName().equals("id")){ response.getWriter().print(c.getValue()); } } } }
3.cookie的生命周期
Cookie不只有name和value,Cookie还有生命,即cookie在客户端浏览器的有效时间,可以通过setMaxAge(int) 来设置Cookie的有效时间
cookie.setMaxAge(-1):cookie的maxAge的默认值就是-1,表示在浏览器内存中存活,一旦关闭浏览器,那cookie就会消失。
cookie.setMaxAge(60*60): 表示cookie对象可以存活一个小时。当生命值大于0时,浏览器会把cookie保存到硬盘上,就算关闭浏览器,或者重启电脑,cookie在生命值时间内也是存活的。
cookie.setMaxAge(0): 表示cookie被作废,也就是说,如果原来浏览器已经保存了cookie,那么可以通过设置生命值为0来删除该cookie。
4.cookie示例2
显示上次访问时间
* 创建Cookie,名称为lasttime,值为当前访问时间,添加到response中
* 在AServlet中获取请求名为lasttime的Cookie
* 如果不存在就输出“欢迎首次访问本站”,如果存在就输出上次访问时间
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); Cookie[] cookie=request.getCookies(); String str="欢迎首次访问本站"; boolean flag=true; if(cookie!=null){ for(Cookie c:cookie){ if(c.getName().equals("lasttime")){ str="您上次访问时间是:"+c.getValue(); c.setValue(new Date().toString()) response.addCookie(c); flag=false; } } } if(flag){ Cookie co=new Cookie("lasttime",new Date().toString()); response.addCookie(co); } response.getWriter().print(str); }
5.cookie中包含中文
Cookie的name和value都不能使用中文,如果希望在Cookie中使用中文,那么需要先对中文进行URL编码,然后把编码后的字符放到Cookie中。
(1)对含有中文内容的cookie进行编码并保存
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); String name = URLEncoder.encode("姓名","utf-8"); String value = URLEncoder.encode("张三","utf-8"); Cookie cookie = new Cookie(name,value); response.addCookie(cookie); response.getWriter().print("添加成功"); }
(2)获取cookie并解码
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); Cookie[] cookie = request.getCookies(); if(cookie!=null) { for(Cookie c:cookie) { String name = URLDecoder.decode(c.getName(),"utf-8"); String value = URLDecoder.decode(c.getValue(),"utf-8"); response.getWriter().print(name+":"+value); } } }
6.Cookie的路径
6.1什么是Cookie的路径
假设WEB应用A,向客户端发送了100个Cookie,则客户端无论访问应用A的哪个Servlet都会把这100个Cookie包含在请求中!但是也许只有AServlet需要读取请求中的Cookie,而其他Servlet根本就不会获取请求中的Cookie。这说明客户端浏览器有时发送这些Cookie是多余的!
可以通过设置Cookie的path来指定浏览器在访问什么样的路径时,包含什么样的Cookie。
6.2Cookie路径与请求路径的关系
可以使用cookie.setPath(路劲) 来设置cookie的路径。
下面来看看Cookie路径的作用:
如下所示是客户端浏览器保存的3个Cookie的路径(path):
a: /cookietest;
b: /cookietest/servlet;
c: /cookietest/jsp;
下面是浏览器请求的URL:
A: http://localhost:8080/cookietest/AServlet;
B: http://localhost:8080/cookietest/servlet/BServlet;
C: http://localhost:8080/cookietest/jsp/CServlet;
- 请求A时,会在请求中包含a;
- 请求B时,会在请求中包含a、b;
- 请求C时,会在请求中包含a、c;
也就是说,请求路径如果包含了Cookie路径,那么会在请求中包含这个Cookie,否则不会请求中不会包含这个Cookie。
* A请求的URL包含了“/cookietest”,所以会在请求中包含路径为“/cookietest”的Cookie;
* B请求的URL包含了“/cookietest”,以及“/cookietest/servlet”,所以请求中包含路径为“/cookietest”和“/cookietest/servlet”两个Cookie;
* C请求的URL包含了“/cookietest”,以及“/cookietest/jsp”,所以请求中包含路径为“/cookietest”和“/cookietest/jsp”两个Cookie;
6.3设置Cookie的路径
设置Cookie的路径需要使用setPath()方法,例如:
cookie.setPath(“/cookietest/servlet”);
当访问http://localhost:8080/cookietest/servlet/BServlet;浏览器会发送该cookie
如果访问http://localhost:8080/cookietest/jsp/CServlet; 浏览器不会发送该cookie
如果没有设置Cookie的路径,那么Cookie路径的默认值当前访问资源所在路径,例如:
* 访问http://localhost:8080/cookietest/AServlet时添加的Cookie默认路径为/cookietest;
* 访问http://localhost:8080/cookietest/servlet/BServlet时添加的Cookie默认路径为/cookietest/servlet;
* 访问http://localhost:8080/cookietest/jsp/BServlet时添加的Cookie默认路径为/cookietest/jsp;
三、HttpSession
1.HttpSession概述
1.1 什么是HttpSession
javax.servlet.http.HttpSession接口表示一个会话,一般会把一个会话内需要共享的数据保存到HttpSession对象中。
1.2 如何获取HttpSession对象
- HttpSession request.getSession();
如果当前会话已经有了session对象那么直接返回,如果当前对象还不存在session,那么创建一个session对象并返回; - HttpSession request.getSession(boolean);
当参数为true时,与HttpSession request.getSession()相同;
当参数为false时,如果当前Session没有就不创建session,并返回null,如果有就返回当前session。
1.3 HttpSession是域对象
我们已经学了HttpServletRequest,ServletContext两个域对象,而HttpSession也是域对象。作为域对象可以存储数据。
* setAttribute(String name,Object value);
* getAttribute(String name);
* void removeAttribute(String name);
* Enumeration getAttributeNames();
1.4 HttpSession的生命周期
在第一次调用 request.getSession() 方法时,服务器会检查是否已经有对应的session,如果没有就在服务器内存 中创建一个session并返回。
当一段时间内session没有被使用(默认为30分钟),则服务器会销毁该session。
如果服务器非正常关闭(强行关闭),没有到期的session也会跟着销毁。
如果调用session提供的invalidate( ) ,可以立即销毁session。
注意:服务器正常关闭,再启动,Session对象会进行钝化和活化操作。同时如果服务器钝化的时间在session 默认销毁时间之内,则活化后session还是存在的。否则Session不存在。 如果JavaBean 数据(例如:Person类)在session钝化时,没有实现Serializable 则当Session活化时,会消失。
2、作用范围:一次会话。
Session说明:
对于一个浏览器,一次会话而言,只要session未过期,服务器中只会为本次会话提供一个session对象。
当关闭浏览器(会话结束),再重新打开浏览器器后访问应用后,服务器会再次为该浏览器的本次会话重新创建session对象
即:多个浏览器会有不同的session对象。
2.登陆案例
需要的页面:
* login.jsp:登录页面,提供登录表单;
* success.jsp:主页,登录成功后跳转到该页面;
* fail.jsp:主页,如果没有登录,显示未登陆成功;
Servlet:
LoginServlet:在login.jsp页面提交表单时,请求本Servlet。在本Servlet中获取用户名、密码进行校验,如果用户名、密码错误,显示“用户名或密码错误”,如果正确保存用户名session中,然后重定向到success.jsp;
当用户没有登录时访问success.jsp或fail.jsp,显示“您还没有登录”。如果用户在login.jsp登录成功后到达success.jsp页面会显示当前用户名,而且不用再次登录去访问fail.jsp也会显示用户名。因为多次请求在一个会话范围,success.jsp和fail.jsp都会到session中获取用户名,session对象在一个会话中是相同的,所以都可以获取到用户名!
* Login.jsp
<html> <head> <base href="<%=basePath%>"> <title>登录界面</title> </head> <body> <form name="f1" id="f1" action="/myapp/lServlet" method="post"> <table> <tr> <td>Login:</td> <td><input type="text" name="userName"></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="password"></td> </tr> <tr> <td colspan="2"><input type="submit"></td> </tr> </table> </form> </body></html>
- success.jsp
<html> <head> <base href="<%=basePath%>"> <title>登录成功页面</title> </head> <body> <% String userName=(String)session.getAttribute("userName"); out.print("当前用户:"+userName); %> </body></html>
- fail.jsp
<body> <% out.print("用户登录失败,5s后将跳转到登录页面"); response.setHeader("Refresh","5,URL=http://localhost:8080/day08_31/session/login.jsp"); %> </body>
- LoginServlet.java
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置接收数据的解码格式 request.setCharacterEncoding("utf-8"); //获取参数 String userName=request.getParameter("userName"); String password=request.getParameter("password"); System.out.println("userName="+userName); //判断用户名和密码是否匹配(张三,123456) if((userName!=null&&userName.equals("张三"))&&(password!=null&&password.equals("123456"))){ //如果登录成功,将用户名存放在session中 HttpSession session=request.getSession(); session.setAttribute("userName", userName); response.sendRedirect("/myapp/session/success.jsp"); }else{ //如果登录失败 response.sendRedirect("/myapp/session/fail.jsp"); } }
3.HttpSession的实现原理
获取session对象后,是保存在服务器内存中的。服务器在响应时会给客户端传送一个sessionId的值(一个cookie中保存了sessionId)。客户端带走的是sessionId,而数据是保存在session中。
当客户端再次访问服务器时,在请求中会带上sessionId,而服务器会通过sessionId找到session。而不需要重新在创建session。
这个sessionId对应就是浏览器cookie中的JsessionId。服务在首次创建session,会将sessionId封装到cookie中,服务器响应给客户端时返回了该cookie。当客户端再次访问服务器时,会将该cookie封装到request。
4. session与浏览器
sessionId是通过Cookie发送给客户端的,但这个cookie的默认生命值是-1,只在浏览器内存中存在,也就是说如果用户关闭立刻浏览器,那么这个Cookie就丢失了。
当用户再次打开浏览器访问服务器,就不会再有sessionId(在浏览器中是JsessionId)发送给服务器。那么服务器会认为没有session,所有服务器会创建一个新session对象,并在响应时将新的sessionId以cookie的形式发送给浏览器。
而原先的session对象因为长时间没被调用,所以服务器会在一定时间后把该session删除。该时间长在Tomcat中默认配置为30分钟,可以在tomcat配置文件中还找到,tomcat文件夹中的conf文件中的web.xml可以找到。
也可以单独为应用设置session,即在项目的web.xml中配置session的过期时间(单位分钟)
<session-config> <session-timeout>30</session-timeout></session-config>
session失效时间也说明一个问题,如果打开一个浏览器页面长时间不去操作,超出30分钟后,再去点击链接或者表单,原先的session已经丢失。
5.session其他常用api
- String getId():获取sessionId;
- int getMaxInactiveInterval():获取session可以的最大不活动时间(秒),默认为30分钟。当session在30分钟内没有使用,那么Tomcat会在session池中移除这个session;
- void setMaxInactiveInterval(int interval):设置session允许的最大不活动时间(秒),如果设置为1秒,那么只要session在1秒内不被使用,那么session就会被移除;
- long getCreationTime():返回session的创建时间,返回值为当前时间的毫秒值;
- long getLastAccessedTime():返回session的最后活动时间,返回值为当前时间的毫秒值;
- void invalidate():让session失效!调用这个方法会让session失效,当session失效后,客户端再次请求,服务器会给客户端创建一个新的session,并在响应中给客户端新session的sessionId;
- boolean isNew():查看session是否为新。当客户端第一次请求时,服务器为客户端创建session,但这时服务器还没有响应客户端,也就是还没有把sessionId响应给客户端时,这时session的状态为新。
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置编码格式 request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); //创建或者获取session HttpSession session=request.getSession(); //获取sessionId String sessionId=session.getId(); //获取session可以的最大不活动时间(秒),默认为30分钟。 int time=session.getMaxInactiveInterval(); System.out.println("session有效期="+time); //设置session可以的最大不活动时间(秒) session.setMaxInactiveInterval(20); int time2=session.getMaxInactiveInterval(); System.out.println("新的session有效期="+time2); //获取session域参数 String val=(String)session.getAttribute("name"); response.getWriter().print("session中的值为:"+val+"</br>sessionId="+sessionId); }
6.URL重写
session依赖Cookie,那么如果客户端浏览器禁用了Cookie,即浏览器不用再接收cookie,那么sessionId也将不会被再次接收。此时可以通过URL重写来解决这种问题。这种方法让服务器收到的每个请求中都带有sessioinId。在每个页面中的每个链接和表单中都添加名为jSessionId的参数,值为当前sessionid。当用户点击链接或提交表单时服务器可以通过获取jSessionId这个参数来得到客户端的sessionId,找到sessoin对象。
index.jsp
<body><h1>URL重写</h1><a href='/myapp/index.jsp;jsessionid=<%=session.getId() %>' >主页</a><form action='/myapp/index.jsp;jsessionid=<%=session.getId() %>' method="post"> <input type="submit" value="提交"/></form> </body>
也可以使用response.encodeURL()对每个请求的URL处理,这个方法会自动追加jsessionid参数,与上面手动添加是一样的效果。
<a href='<%=response.encodeURL("/day06_5/index.jsp") %>' >主页</a><form action='<%=response.encodeURL("/day06_5/index.jsp") %>' method="post"> <input type="submit" value="提交"/></form>
使用response.encodeURL()更加“智能”,它会判断客户端浏览器是否禁用了Cookie,如果禁用了,那么这个方法在URL后面追加jsessionid,否则不会追加。
- Javaweb基础之cookie&session
- JavaWeb基础---Cookie和Session
- JavaWeb之Cookie&&Session详解
- Javaweb之cookie和session
- Javaweb之cookie和session
- javaWeb之Cookie和Session
- Javaweb核心之session&cookie
- JavaWeb学习篇之----Session&&Cookie
- JavaWeb系列之八(Cookie&Session)
- JavaWeb学习篇之----Session&&Cookie
- Javaweb学习之Session和Cookie
- JavaWeb之Servlet:Cookie 和 Session
- JavaWeb学习篇之----Session&&Cookie
- JavaWeb学习篇之----Session&&Cookie
- JavaWeb之会话技术Cookie&Session
- 【JavaWeb】cookie与session
- javaweb--Cookie&Session
- JavaWeb--Session、Cookie
- 【HTML5学习笔记】33:CSS3过渡效果
- 病闲细笔
- Unity编辑器拓展之一:ReorderableList可重新排序的列表框(简单使用)
- bootstrap 利用jquery 添加disabled属性
- Oracle 用hint来影响执行计划
- Javaweb基础之cookie&session
- ionic2+启动白屏问题-------之补充解决之道
- Subway
- 信号在android源码/external/dhcpcd 源码项目中的应用解读分析
- (13)会话和cookie技术
- 正则表达式
- X250无法开机问题解决
- 【操作系统学习日记】2.BIOS(基本输入输出系统)
- 一起艳学Centos7(三)