欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

会话跟踪技术----cookie和session

程序员文章站 2024-03-20 12:03:52
...

Cookie

什么叫Cookie
Cookie 是网站用来在客户端保存识别用户的一种小文件
一般用Cookie可以保存用户登录信息、购物数据信息等一系列微小信息。

其实Cookie就是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie、再发送给服务器。

注意,不同浏览器之间是不共享Cookie的。

Cookie与HTTP头

Cookie是通过HTTP请求和响应头在客户端和服务器端传递的:
Cookie:请求头,客户端发送给服务器端;
格式:Cookie: a=A; b=B; c=C。即多个Cookie用分号离开;
Set-Cookie:响应头,服务器端发送给客户端;
一个Cookie对象一个Set-Cookie:
Set-Cookie: a=A
Set-Cookie: b=B
Set-Cookie: c=C

Cookie的覆盖
如果服务器端发送重复的Cookie那么会覆盖原有的Cookie,
如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA。

Cookie示例(Servlet)
服务端ServletA将一个键值对 以Cookie的形式响应给客户端,客户端存储在本地,然后再访问ServletB,ServletB得到请求中的所有Cookie ,并在控制台打印出来。
我们这个案例是,客户端访问AServlet,AServlet在响应中添加Cookie,浏览器会自动保存Cookie。然后客户端访问BServlet,这时浏览器会自动在请求中带上Cookie,BServlet获取请求中的Cookie打印出来。

注:
使用repsonse.addCookie()方法向浏览器保存Cookie
使用request.getCookies()方法获取浏览器归还的Cookie

代码实现:
AServlet.java

/**
 * 给客户端发送Cookie
 * @author Administrator
 *
 */
public class AServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        
        String id = UUID.randomUUID().toString();//生成一个随机字符串
        Cookie cookie = new Cookie("id", id);//创建Cookie对象,指定名字和值
        response.addCookie(cookie);//在响应中添加Cookie对象
        response.getWriter().print("已经给你发送了ID");
    }
}

BServlet.java

/**
 * 获取客户端请求中的Cookie
 * @author Administrator
 *
 */
public class BServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        
        Cookie[] cs = request.getCookies();//获取请求中的Cookie
        if(cs != null) {//如果请求中存在Cookie
            for(Cookie c : cs) {//遍历所有Cookie
                if(c.getName().equals("id")) {//获取Cookie名字,如果Cookie名字是id
                    response.getWriter().print("您的ID是:" + c.getValue());//打印Cookie值
                }
            }
        }
    }
}

Cookie的生命

**setMaxAge(int)**来设置Cookie的有效时间, 以秒为单位
**cookie.setMaxAge(60)**表示这个Cookie会被浏览器保存到硬盘上60秒。
cookie.setMaxAge(-1):cookie的maxAge属性的默认值就是-1,表示只在浏览器内存中存活。一旦关闭浏览器窗口,那么cookie就会消失。
cookie.setMaxAge(0)cookie生命等于0是一个特殊的值,它表示cookie被作废!也就是说,如果原来浏览器已经保存了这个Cookie,那么可以通过Cookie的setMaxAge(0)来删除这个Cookie。无论是在浏览器内存中,还是在客户端硬盘上都会删除这个Cookie。

创建Cookie,名为lasttime,值为当前时间,添加到response中;
在AServlet中获取请求中名为lasttime的Cookie;
如果不存在输出“您是第一次访问本站”,如果存在输出“您上一次访问本站的时间是xxx”;

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        
        //创建Cookie对象,名为lasttime,值为当前时间
        Cookie cookie = new Cookie("lasttime", new Date().toString());
        //设置Cookie在客户端的有效时间为1小时
         cookie.setMaxAge(60 * 60);
         //添加Cookie到response中
        response.addCookie(cookie);
        
        //获取请求中的Cookie
        Cookie[] cs = request.getCookies();
        String s = "您是首次访问本站!";
        if(cs != null) {//如果请求中存在Cookie
            for(Cookie c : cs) {//循环遍历请求中的Cookie
                //如果Cookie名为lasttime
                if(c.getName().equals("lasttime")) {
                    s = "您上次的访问时间是:" + c.getValue();
                }
            }
        }
        //打印s到客户端
        response.getWriter().print(s);
    }

Cookie中保存中文
Cookie的name和value都不能使用中文,如果希望在Cookie中使用中文,那么需要先对中文进行URL编码,然后把编码后的字符串放到Cookie中。
向客户端响应中添加Cookie

//使用URL编码
String name = URLEncoder.encode("姓名", "UTF-8");
String value = URLEncoder.encode("张三", "UTF-8");
//编码后的字符串保存到Cookie中
Cookie c = new Cookie(name, value);
c.setMaxAge(3600);
response.addCookie(c);

从客户端请求中获取Cookie

response.setContentType("text/html;charset=utf-8");
Cookie[] cs = request.getCookies();
if(cs != null) {
         for(Cookie c : cs) {
            //把Cookie的name和value使用URL解码后再打印
            String name = URLDecoder.decode(c.getName(), "UTF-8");
            String value = URLDecoder.decode(c.getValue(), "UTF-8");
            String s = name + ": " + value + "<br/>";
            response.getWriter().print(s);
 }

HttpSession

什么是HttpSesssion
javax.servlet.http.HttpSession是由JavaWeb提供的,用来会话跟踪的类。session是服务器端对象,保存在服务器端!!!
HttpSession接口表示一个会话,我们可以把一个会话内需要共享的数据保存到HttSession对象中!

获取HttpSession对象
HttpSession request.getSesssion():如果当前会话已经有了session对象那么直接返回,如果当前会话还不存在会话,那么创建session并返回;
HttpSession request.getSession(boolean):当参数为true时,与requeset.getSession()相同。如果参数为false,那么如果当前会话中存在session则返回,不存在返回null;

HttpSession是域对象

我们已经学习过HttpServletRequest、ServletContext,它们都是域对象,现在我们又学习了一个HttpSession,
它也是域对象。它们是Servlet的三大域对象。

HttpServletRequest:一个请求创建一个request对象,所以在同一个请求中可以共享request,
例如一个请求从AServlet转发到BServlet,那么AServlet和BServlet可以共享request域中的数据;

ServletContext:一个应用只创建一个ServletContext对象,
所以在ServletContext中的数据可以在整个应用*享,只要不启动服务器,
那么ServletContext中的数据就可以共享

HttpSession:一个会话创建一个HttpSession对象,
同一会话中的多个请求中可以共享session中的数据;

HttpSession和HttpServletRequest、ServletContext 一样 有着如下域方法
void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性,
例如:session.setAttribute(“xxx”,“XXX”),在session中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。
请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同;

Object getAttribute(String name):用来获取session中的数据,当前在获取之前需要先去存储才行,
例如:String value = (String) session.getAttribute(“xxx”);,获取名为xxx的域属性;

void removeAttribute(String name):用来移除HttpSession中的域属性,
如果参数name指定的域属性不存在,那么本方法什么都不做;

Enumeration getAttributeNames():获取所有域属性的名称;

登录案例
需要的页面:
login.html:登录页面,提供登录表单;
Index1Serlvet:回写当前用户名称,如果没有登录,显示您还没登录;
index2Serlve回写当前用户名称,如果没有登录,显示您还没登录
LoginServlet:在login.html页面提交表单时,请求本Servlet。在本Servlet中获取用户名、密码进行校验,如果用户名、密码错误,显示“用户名或密码错误”,如果正确保存用户名session中,然后重定向到index1Servlet;
当用户没有登录时访问index1Servlet或index1Servlet,显示“您还没有登录”。如果用户在login.html登录成功后到达index1Servlet页面会显示当前用户名,而且不用再次登录去访问index2Servlet也会显示用户名。因为多次请求在一个会话范围,index1Servlet和index2Servlet都会到session中获取用户名,session对象在一个会话中是相同的,所以都可以获取到用户名!

public class LoginServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        
        //获取表单参数username
        String username = request.getParameter("username");
        
        //如果用户为root表示登录失败
        if(username.equalsIgnoreCase("scott")) {
            response.getWriter().print("用户名或密码错误!");
        } else {
            //获取session对象
            HttpSession session = request.getSession();
            //在session中保存用户名
            session.setAttribute("username", username);
            //重定向指定的页面。
            response.sendRedirect("/index1Servlet");
       }
    }
}

HTTP协议是无状态协议。JavaWeb服务器是无法记录客户端浏览器的身份的。若需要实现回话跟踪,也需要使用一个标识。
当客户端浏览器首次访问服务器端的时候,并且当服务器首次使用session 此时要创建session,session是保存在服务器端(这个Session中可以保存一些数据)。然后,响应客户端浏览器的时候,会将这个Session的ID以Cookie的形式返回给客户端浏览器,这个SessionID在客户端就以Cookie的形式保存了。
当客户端再次访问服务器时,在请求中会带上sessionId,而服务器会通过sessionId找到对应的session,而无需再创建新的session。这样,服务器就辨识出了哪个客户端回话了。

session与浏览器
session保存在服务器,而sessionId通过Cookie发送给客户端,但这个Cookie的生命为-1,即只在浏览器内存中存在,也就是说如果用户关闭了浏览器,那么这个Cookie就丢失了。
当用户再次打开浏览器访问服务器时,就不会有sessionId发送给服务器,那么服务器会认为你没有session,所以服务器会创建一个session,并在响应中把sessionId中到Cookie中发送给客户端。

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 doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
 
         response.setContentType("text/html;charset=UTF-8");
         //使用request对象的getSession()获取session,如果session不存在则创建一个
         HttpSession session = request.getSession();
         //获取session的Id
         String sessionId = session.getId();
         //判断session是不是新创建的
         if (session.isNew()) {
             response.getWriter().print("session创建成功,session的id是:"+sessionId);
         }else {
             response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);
         }
     }