cookie&session

本文详细介绍了会话管理技术的基本概念及其在Web开发中的应用,包括客户端Cookie技术和服务器端Session技术的工作原理、核心技术及实际应用场景。

1. 什么是会话

是指浏览器和服务端之间的数据传输(用户登录,购物车等)

会话管理就是管理浏览器和服务端会话过程产生的会话数据

常用的会话技术:

数据保存在浏览器的Cookie技术

数据保存在服务端的Session技术

2. Cookie技术

1. 什么是Cookie

Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器,当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是各自用户自己的数据了

2. Cookie技术核心API

Cookie类:用于存储会话数据,常用方法如下:
- 构造Cookie对象

Cookie(String name,String value)
  • 设置cookie
void setPath(String uri):设置cookie的有效访问路径
void setMaxAge(int expiry):设置cookie的有效时间
void setValue(String newValue):设置cookie的值
  • 发送cookie到浏览器保存
void response.addCookie(Cookie cookie):发送cookie
  • 服务器端接收cookie
Cookie[] request.getCookies():接收cookie

Demo:

public class CookieDemo extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 1.创建Cookie对象
        Cookie cookie = new Cookie("name", "value");

        // 2.设置Cookie参数
        // 2.1设置Cookie的有效路径
        cookie.setPath("/hello");// 默认就是web项目的地址
        // 2.2设置Cookie的有效时间
        cookie.setMaxAge(20);// 此cookie只存活20秒,从最后不调此cookie开始计算
        cookie.setMaxAge(-1);// 此cookie保存在浏览器内存中,关闭浏览器则销毁此cookie
        cookie.setMaxAge(0);// 删除与此cookie同名的cookie

        // 3.把数据发送到浏览器
        response.addCookie(cookie);

        // 4.服务端接收来自浏览器的cookie
        // 方法一:
        // String name=request.getHeader("cookie");
        // System.out.println(name);
        // 方法二:
        Cookie[] cookies = request.getCookies();

        for (Cookie c : cookies) {
            String name = c.getName();
            String value = c.getValue();
            System.out.println(name + "=" + value);
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

3. Cookie原理

  1. 服务器创建Cookie对象,把会话数据存储到Cookie对象中
new Cookie("name","value");
  1. 服务器发送cookie信息到浏览器
response.addCookie(cookie);//其实是隐藏发送了一个set-cookie名称的响应头
  1. 浏览器得到服务器发送的cookie,然后保存在浏览器端
  2. 浏览器下次访问服务器时,会带着cookie信息
包含在http的请求头里
  1. 服务器接收到浏览器带来的cookie信息
request.getCookies();

4.Cookie的细节

  1. void setPath(String uri):设置cookie的有效访问路径,有效访问路径指的是Cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着Cookie信息,否则不带Cookie信息,默认是在当前web项目的路径下
  2. void setMaxAge(int expiry):设置cookie的有效时间

    expiry可以是正整数,负整数和零

    正整数:表示Cookie数据保存浏览器的缓存到硬盘中,数值表示保存的时间

    负整数:表示Cookie数据保存到浏览器的内存中,浏览器关闭Cookie就丢失了

    零:表示删除同名的Cookie数据

  3. Cookie数据类型只能保存非中文字符串类型的。可以保存多个Cookie,但是浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4kb

5. Cookie应用:显示用户上次访问的时间

功能实现逻辑:

把时间保存在Cookie中,每次访问从Cookie里面调用

第一次访问:
1. 获取当前时间,显示到浏览器上
2. 创建Cookie对象,时间作为cookie值,名为:lastTime
3. 把cookie发送到浏览器保存

第n次访问:
1. 获取cookie的数据,取出名为lastTime的cookie
2. 得到cookie的值(上次访问时间)
3. 显示上次访问时间到浏览器上
4. 更新名为lastTime的cookie,值设置为当前时间
5. 把更新后的cookie发送给浏览器保存

代码实现:
public class CookieDemo2 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        // 获取当前时间
        SimpleDateFormat t = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String curTime = t.format(new Date());

        // 取得cookie
        Cookie[] cookies = request.getCookies();
        String lastTime = null;

        // 第n次访问
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("lastTime")) {
                    // 有lastTime的cookie,已经是第n次访问
                    lastTime = cookie.getValue();//上次访问的时间

                    // 第n次访问
                    // 1.把上次访问时间显示到浏览器上
                    response.getWriter().write(
                            "欢迎回来,你上次访问的时间是: " + lastTime + ",当前时间为: "+ curTime);

                    // 2.更新cookie
                    cookie.setValue(curTime);
                    cookie.setMaxAge(1 * 30 * 24 * 60 * 60);

                    // 3.把更新后的cookie发送到浏览器
                    response.addCookie(cookie);

                    break;              
                }

            }
        }

        // 第一次访问 没有cookie 或有cookie但没有名为lastTime的cookie
        if (cookies == null || lastTime == null) {
            // 1.显示当前时间到浏览器上
            response.getWriter().write("你是首次访问本网站,当前时间是: " + curTime);

            // 2.创建Cookie对象
            Cookie cookie = new Cookie("lastTime", curTime);
            cookie.setMaxAge(1 * 30 * 24 * 60 * 60);

            // 3.把cookie发送到浏览器保存
            response.addCookie(cookie);
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

6. Cookie应用:查看用户浏览过的商品

功能实现逻辑:

这里写图片描述

代码实现:
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map.Entry;

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 ListServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        // 显示商品列表
        out.write("书籍列表: <br/>");
        for (Entry<String, Book> b : Db.getBooks().entrySet()) {
            out.write("<a href='" + request.getContextPath()
                    + "/servlet/detailServlet?id=" + b.getKey()
                    + "' target='_blank'>" + b.getValue().getName()
                    + "</a><br/>");
        }

        // 显示浏览过的商品
        out.write("<br/>浏览过的 : <br/>");
        Cookie[] cookies = request.getCookies();
        for (int i = 0; cookies != null && i < cookies.length; i++) {
            if (cookies[i].getName().equals("history")) {
                String[] ids = cookies[i].getValue().split("\\-");
                for (String s : ids) {
                    out.write(Db.getBooks().get(s).getName() + "<br/>");
                }
            }
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }
}
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Map.Entry;

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 DetailServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();

        // 显示商品详情
        out.write("书籍详情: <br/>");
        String id = request.getParameter("id");
        for (Entry<String, Book> b : Db.getBooks().entrySet()) {
            if (id.equals(b.getKey())) {
                out.write(b.getValue().getId() + "<br/>");
                out.write(b.getValue().getName() + "<br/>");
                out.write(b.getValue().getPrice() + "<br/>");
                out.write(b.getValue().getAuthor() + "<br/>");
            }
        }

        // 回写cookie,保存最后浏览的商品id
        String history = buildIds(id, request);
        Cookie cookie = new Cookie("history", history);
        cookie.setMaxAge(1 * 30 * 24 * 60 * 60);
        cookie.setPath("/cookieTest");
        response.addCookie(cookie);
    }

    private String buildIds(String id, HttpServletRequest request) {
        String history = null;
        Cookie[] cookies = request.getCookies();
        for (int i = 0; cookies != null && i < cookies.length; i++) {
            if (cookies[i].getName().equals("history")) {
                history = cookies[i].getValue();
            }
        }
        if (history == null) {
            System.out.println(id);
            return id;
        }
        LinkedList<String> ids = new LinkedList<String>(Arrays.asList(history
                .split("\\-")));
        if (ids.contains(id)) {
            ids.remove(id);
        } else {
            if (ids.size() >= 3) { // 最多显示3条浏览历史
                ids.removeLast();
            }
        }
        ids.addFirst(id);

        StringBuffer sb = new StringBuffer();

        for (int j = 0; j < ids.size(); j++) {
            if (j != ids.size() - 1) {
                sb.append(ids.get(j)).append("-");
            } else {
                sb.append(ids.get(j));
            }
        }
        System.out.println(sb);

        return sb.toString();
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}
public class Book {
    private String id;
    private String name;
    private double price;
    private String author;

    public Book(String id, String name, double price, String author) {
        super();
        this.id = id;
        this.name = name;
        this.price = price;
        this.author = author;
    }

    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;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}
import java.util.LinkedHashMap;
import java.util.Map;

class Db {
    private static Map<String, Book> books = new LinkedHashMap<String, Book>();
    static {
        books.put("1", new Book("1", "红楼梦", 15, "曹雪芹"));
        books.put("2", new Book("2", "大漠谣", 20, "桐华"));
        books.put("3", new Book("3", "诛仙", 15, "萧鼎"));
        books.put("4", new Book("4", "朝花夕拾", 25, "鲁迅"));
    }

    public static Map<String, Book> getBooks() {
        return books;
    }
}

3. Session技术

1. 什么是Session

Session是服务器端技术,利用这个技术,服务器在运行时可以为每个用户的浏览器创建一个其独享的HttpSession对象,由于session为用户浏览器独享,所以用户在访问服务器的资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他的web资源再从用户的各自session中取出数据为用户服务

2. Session的核心技术

HttpSession类:用于保存会话数据,常用方法如下:
- 创建或得到session对象

HttpSession getSession():直接创建一个Session对象
HttpSession getSession():接收布尔值,设置为true时,在没有找到匹配Session编号的对象时新建一个Session对象
如果设置为false,则当找不到匹配的Session时,返回null
  • 设置session对象
void setMaxInactiveInterval(int interval):设置session的有效时间
默认30分钟自动回收session对象
String getId():得到session编号
void invalidate():销毁session对象
  • 保存会话数据到session对象
void setAttribute(String name,object value):保存数据
Object getAttribute(String name):获取数据
void removeAttribute(String name):清除数据
  • 如何避免浏览器的JSESSIONID的cookie随着浏览器关闭而丢失的问题
解决方法是手动发送一个硬盘保护的cookie给浏览器

Demo:

public class SessionServletDemo extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 1.创建Session对象
        HttpSession session = request.getSession();

        // 2.保存会话数据
        session.setAttribute("name", "eric");

        // 3.取出会话数据
        String name = (String) session.getAttribute("name");
        System.out.println(name);

        // 4.1拿到session的id
        System.out.println(session.getId());
        // 4.2修改session的有效时间
        session.setMaxInactiveInterval(20);
        // 4.3销毁session
        if (session != null) {
            session.invalidate();
        }

        // 5.手动发送一个硬盘保存的cookie给浏览器
        Cookie c = new Cookie("JSESSION", session.getId());
        c.setMaxAge(60 * 60);
        response.addCookie(c);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

3. Session原理

代码解读:HttpSession session=request.getSession();
伪码分析执行过程
1. 第一次访问创建Session对象,给Session对象分配一个唯一的ID,叫JSESSIONID

new HttpSession();
  1. 把JSESSIONID作为Cookie的值发送给浏览器保存
Cookie cookie = new Cookie("JSESSIONID",sessionID);
response.addCookie(cookie);
  1. 第二次访问时,浏览器带着JSESSIONID的cookie访问服务器
  2. 服务器得到JSESSIONID,在服务器的内存中搜索是否存放对应编号的session对象
  3. 如果找到对应编号的session对象,直接返回此对象
  4. 如果找不到对应编号的session对象,创建新的session对象,继续走1的流程

结论:通过JSESSION的cookie值在服务器中找session对象

4. Session应用:用户登录效果

需求:实现用户登录效果,如果登录成功,显示欢迎回来,xxx。如果失败显示登录失败
默认登录页面:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录页面</title>
</head>
<body>
    <form action="/cookieTest/servlet/loginServlet" method="post">
        用户名:<input type="text" name="userName" /> <br /> 
        密码:<input type="text" name="userPwd" /> <br /> 
        <input type="submit" value="登录" />
    </form>
</body>
</html>

登录失败页面:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>信息提示页面</title>
</head>
<body>
    <font color='red' size='3'>亲,你的用户名或密码输入有误!请重新输入!</font>
    <br />
    <a href="/cookieTest/index.html">返回登录界面</a>
</body>
</html>

表单提交后的主处理逻辑:

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class IndexServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        String html = "";

        HttpSession session = request.getSession(false);

        if (session == null) {
            response.sendRedirect(request.getContextPath() + "/index.html");
            return;
        }
        String userName = (String) session.getAttribute("userName");
        if (userName == null) {
            response.sendRedirect(request.getContextPath() + "/index.html");
            return;
        }
        html = "<html><body>欢迎回来," + userName + ",<a href='"
                + request.getContextPath()
                + "/servlet/logoutServlet'>安全退出</a></body></html>";
        out.write(html);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

登录处理逻辑:

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        String userName = request.getParameter("userName");
        String userPwd = request.getParameter("userPwd");

        if ("eric".equals(userName) && "123456".equals(userPwd)) {
            HttpSession session = request.getSession();
            session.setAttribute("userName", userName);
            response.sendRedirect(request.getContextPath() + "/servlet/indexServlet");

        } else {
            response.sendRedirect(request.getContextPath() + "/fail.html");
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

退出处理逻辑:

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LogoutServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession(false);

        if (session != null) {
            session.removeAttribute("userName");
        }

        response.sendRedirect(request.getContextPath() + "/index.html");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

5. Session应用:购物车

public class Book {
    private String id;
    private String name;
    private double price;
    private String author;

    public Book(String id, String name, double price, String author) {
        super();
        this.id = id;
        this.name = name;
        this.price = price;
        this.author = author;
    }

    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;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}
import java.util.LinkedHashMap;
import java.util.Map;

class Db {
    private static Map<String, Book> books = new LinkedHashMap<String, Book>();
    static {
        books.put("1", new Book("1", "红楼梦", 15, "曹雪芹"));
        books.put("2", new Book("2", "大漠谣", 20, "桐华"));
        books.put("3", new Book("3", "诛仙", 15, "萧鼎"));
        books.put("4", new Book("4", "朝花夕拾", 25, "鲁迅"));
    }

    public static Map<String, Book> getBooks() {
        return books;
    }

    public static Book findBookById(String id){
        return books.get(id);
    }
}
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ListServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        out.print("本网站有以下书籍:<br/>");
        Map<String, Book> books = Db.getBooks();
        for (Map.Entry<String, Book> book : books.entrySet()) {
            String url = request.getContextPath() + "/servlet/addCart?id="
                    + book.getKey();
            out.print("<a href='" + response.encodeURL(url) + "'>"
                    + book.getValue().getName() + "</a><br/>");
        }

        String url2 = request.getContextPath() + "/servlet/showCart";
        out.print("<a href='" + response.encodeURL(url2) + "'>查看购物车</a>");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class AddCart extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        String id = request.getParameter("id");
        Book book = Db.findBookById(id);

        HttpSession session = request.getSession();
        List<Book> list = (List<Book>) session.getAttribute("cart");
        if (list == null) {
            list = new ArrayList<Book>();
        }
        list.add(book);

        session.setAttribute("cart", list);

        out.print("购买成功!");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class ShowCart extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print("购物车有以下书籍:<br/>");
        HttpSession session = request.getSession();
        List<Book> books = (List<Book>) session.getAttribute("cart");
        if (books == null) {
            out.print("你还什么都没买呢");
            response.setHeader("refresh", "2;url=" + request.getContextPath()
                    + "/servlet/listServlet");
            return;
        }
        for (Book book : books) {
            out.write(book.getName() + "<br/>");
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值