用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
Cookie是客户端技术,服务器把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。cookie原理:
浏览器第一次访问服务器时,没带有cookie,访问完Servlet1之后带有cookie信息回送给浏览器,存在缓存区。当浏览器第二次访问服务器时就已经带着缓存中的Cookie了,Servlet2此时就知道用户原本购买的信息了。
我们先看一下官方文档的对于Cookie的介绍。
javax.servlet.http.Cookie创建一个Cookie,response接口也定义了一个addCookie方法,它用于在其响应头中增加一个相应的SetCookie头字段。同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。Cookie类方法:
public Cookie(String name, String value) //构造方法setValue getValuesetMaxAge getMaxAge //设置Cookie有效期,不调这个方法 Cookie有效期是浏览器进程周期(用户打开浏览器到用户关闭浏览器)setPath getPath //Cookie的有效目录 默认的有效路径是哪个Servlet发出去的就是哪个servlet下的目录setDomain getDomain // 设置域 如 .sina.com.cngetNameCookie的应用:获取最近访问时间,与清除Cookie
创建模拟网站首页的Servlet, package com.xuda27.cookie; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* * 代表网址首页 */ public class CookieTest1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //服务器向浏览器发送数据 编码以utf-8格式 response.setCharacterEncoding("utf-8"); //通知浏览器以utf-8打开数据 response.setContentType("text/html charset=utf-8"); PrintWriter out = response.getWriter(); out.print("<a href='/JavaWeb_CookieSession/servlet/CookieTest2'>清除Cookie</a><br>"); out.print("您上次访问时间是:"); //获得用户的时间cookie Cookie []cookies = request.getCookies(); for(int i=0;cookies!=null && i<cookies.length;i++){ if(cookies[i].getName().equals("lastAccessTime")){ //得到用户上次访问时间 long cookieValue = Long.parseLong(cookies[i].getValue()); Date date = new Date(cookieValue); out.print(date.toLocaleString()); } } //给用户回送最新的访问时间 //创建名为 lastAccessTime,值为系统当前时间的Cookie Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+""); cookie.setMaxAge(30*24*3600);//cookies有效期 30天 cookie.setPath("/JavaWeb_CookieSession");//设置cookie的有效路径:当前工程 response.addCookie(cookie); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }后台处理servlet:
package com.xuda27.cookie; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 后台清除Cookie * @author eden * */ public class CookieTest2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Cookie与前面的要长得一样 Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+""); cookie.setMaxAge(0);//清除 cookie.setPath("/JavaWeb_CookieSession");//路径要设置一样 response.addCookie(cookie);//浏览器增加空的cookie } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }测试结果:
我们打开firebug可以看到Cookie信息。
当我第一次访问CookieTest1(代表网站首页)时,没有带有Cookie信息所以就没有显示上一次访问的时间,然后Servlet才创建Cookie信息,然后在当我刷新页面时,Servlet就会发现有Cookie信息,这时就把上一次访问的时间给显示出来。当点击清除Cookie时,跳转到cookieTest2(代表后台处理),此时Servlet创建一个空的Cookie将原来Cookie信息覆盖,所以当我再一次访问CookieTest1时,上一次访问时间就没有了。
Session是服务器端技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,用户可以在访问服务器的web资源时,可以把各自的数据放在各自的session中,所以session跟ServletContext和Request一样也是域对象。当用户再去访问服务器中的其它web资源时,其它web资源就可以从用户各自的session中取出数据为用户服务。
Session域的作用范围是:默认情况下是在一个会话期间,当然这个范围我们是可以设置的,设置之后可以在多个会话之间。那么Session的生命周期是: 1. Session什么时候创建: Servlet调用HttpServletRequest.getSession(true)这样的语句时才会被创建。 2. Session什么时候销毁: Session在下列情况下被删除:
程序调用HttpSession.invalidate()距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间服务器进程被停止再次注意关闭浏览器只会使存储在客户端浏览器内存中的session的cookie失效,不会使服务器端的session对象失效。
服务器创建session出来后,会把session的id号,以cookie的形式回写给浏览器,这样,只要浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现浏览器带session id过来了,就会使用内存中与之对应的session为之服务。
图解:
浏览器访问Servlet1时,通过调用request.getSession()方法判断服务器中是否含有该session,如果没有则创建,如果有直接调用。因为第一次调用则创建session,并获取session的id,将这个id以Cookie形式会写给浏览器。当浏览器带着Cookie访问servlet2时,调用request.getsession 服务器发现服务器端的session id与cookie的值是否相同,相同直接为它服务。
内部原理,用代码实现 类似这样:
//获取session的Id String sessionId = session.getId(); //将session的Id存储到名字为JSESSIONID的cookie中 Cookie cookie = new Cookie("JSESSIONID", sessionId); //设置cookie的有效路径 cookie.setPath(request.getContextPath()); response.addCookie(cookie);修改session默认生命周期:
HttpSession session = request.getSession(); String sessionId = session.getId(); Cookie cookie = new Cookie("JSESSIONID", sessionId); cookie.setPath("/JavaWeb_CookieSession");//设置session的有效路径,覆盖默认的session的路径 cookie.setMaxAge(30*60);//设置时长为30分钟 response.addCookie(cookie); session.setAttribute("name", "你好!世界!");取出session中的值:
resp.addHeader("content-type", "text/html;charset=utf-8"); resp.setCharacterEncoding("utf-8"); PrintWriter out = resp.getWriter(); String name = (String) req.getSession().getAttribute("name"); out.print(name);如果浏览器禁用Cookie中就无法使用上面的代码来取得存在Cookie中的session id,无法与服务器中的session id匹配。
所以在浏览器禁用Cookie时,怎么来解决session的数据共享问题呢?
response.encodeRedirectURL(java.lang.String url) 用于对sendRedirect方法后的url地址进行重写。response.encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写 response.addHeader("content-type", "text/html;charset=utf-8"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); //创建session request.getSession(); //会在原有的url后面加上 JSESSIONID 地址重写 String url1 = response.encodeURL("/JavaWeb_CookieSession/servlet/SessionTest1"); String url2 = response.encodeURL("/JavaWeb_CookieSession/servlet/SessionTest2"); out.print("<a href='"+url1+"'>说</a><br>"); out.print("<a href='"+url2+"'>看</a>");在禁用Cookie之后,这两个方法会给地址重写。
它会在原有的地址后面加上 session id号。而如果不禁用Cookie则超链接的地址则不会重写。