【简记】Java Web 内幕——Cookie与Session简介和使用

本文内容:

  • 会话场景
  • Cookie类
  • HttpSession类
  • 使用Demo

会话场景

登录场景:
小张: 输入“张三” (保存数据: context.setAttribute(“name”,”张三”)) -> 用户主页(显示“张三”)
小李: 输入“李四”(保存数据:context.setAttribute(“name”,”李四”)) -> 用户主页(显示“李四”)

问题: context是所有用户公有的资源,会覆盖数据。

小张: 输入“张三”(保存数据: request.setAttribute(“name”,”张三”))- > 用户主页(显示“张三”)

问题: 一定要使用转发技术来跳转页面!

※解决办法: 可以使用session域对象来保存会话数据!


会话技术

Cookie技术:会话数据保存在浏览器客户端。
Session技术:会话数据保存在服务器端。


Cookie技术

Cookie类:用于存储会话数据

1)构造Cookie对象
Cookie(java.lang.String name, java.lang.String value)
2)设置cookie
void setPath(java.lang.String uri) :设置cookie的有效访问路径
void setMaxAge(int expiry) : 设置cookie的有效时间(本地)(注意这里与Session不同)
void setValue(java.lang.String newValue) :设置cookie的值

3)发送cookie到浏览器端保存
void response.addCookie(Cookie cookie) : 发送cookie

4)服务器接收cookie
Cookie[] request.getCookies() : 接收cookie


Cookie原理

1)服务器创建cookie对象,把会话数据存储到cookie对象中。
new Cookie(“name”,”value”);

2) 服务器发送cookie信息到浏览器
response.addCookie(cookie);
举例: set-cookie: name=eric (隐藏发送了一个set-cookie名称的响应头)

3)浏览器得到服务器发送的cookie,然后保存在浏览器端。

4)浏览器在下次访问服务器时,会带着cookie信息
举例: cookie: name=eric (隐藏带着一个叫cookie名称的请求头)

5)服务器接收到浏览器带来的cookie信息
request.getCookies();


Cookie的细节

1)void setPath(java.lang.String uri) :设置cookie的有效访问路径。有效路径指的是cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息。

2)void setMaxAge(int expiry) : 设置cookie的有效时间。
正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。
负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!
零:表示删除同名的cookie数据

3)Cookie数据类型只能保存非中文字符串类型的。可以保存多个cookie,但是每个域名最多存放50个Cookie(Chrome浏览器),每个Cookie的大小限制为4KB(Chrome可以更大)。

public class CookieDemo1 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println(Charset.defaultCharset());
        //1.创建Cookie对象
        Cookie cookie1 = new Cookie("name","eric");
        Cookie cookie2 = new Cookie("email","jacky@qq.com");



        /**
         * 1)设置cookie的有效路径。默认情况:有效路径在当前web应用下。
         * 默认情况下,当符合有效路径,浏览器就会把cookie又发回到服务器端
         */
        cookie1.setPath("");
        cookie2.setPath("");

        /**
         * 2)设置cookie的有效时间
         * 正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。
         负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!
         零:表示删除同名的cookie数据

         */
        //cookie1.setMaxAge(20); //20秒,从最后不调用cookie开始计算
        cookie1.setMaxAge(-1); //cookie保存在浏览器内存(会话cookie)
        //cookie1.setMaxAge(0); // 会删除名为name的Cookie


        //2.把cookie数据发送到浏览器(通过响应头发送: set-cookie名称)
        //response.setHeader("set-cookie", cookie1.getName()+"="+cookie1.getValue());
        //推荐使用这种方法,避免手动发送cookie信息
        response.addCookie(cookie1);
        response.addCookie(cookie2);




        //3.接收浏览器发送的cookie信息
        /*String name = request.getHeader("cookie");
        System.out.println(name);*/
        Cookie[] cookies = request.getCookies();
        //注意:判断null,否则空指针
        if(cookies!=null){
            //遍历
            for(Cookie c:cookies){
                String name = c.getName();
                String value = c.getValue();
                System.out.println(name+"="+value);
            }
        }else{
            System.out.println("没有接收cookie数据");
        }

    }

}

显示用户上次登陆的时间
public class HisServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=utf-8");
        Cookie[] cookies = request.getCookies();
        String time = null;
        if(cookies!=null){
            for (Cookie e: cookies) {
                if(e.getName().equals("time")){
                    response.getWriter().print("您上次的登录时间是"+e.getValue());
                    e.setValue(getTime());
                    response.addCookie(e);
                    break;
                }
            }
        }
        if(cookies==null || time==null){ 
            Cookie cookie = new Cookie("time", getTime());
            cookie.setMaxAge(1*30*24*60*60);//保存一个月
            response.addCookie(cookie);
        }


    }

    public String getTime(){
        Date date=new Date();
        DateFormat format=new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
        String time=format.format(date);
        return time;
    }
}

error:
An invalid character [32] was present in the Cookie value

ASCII中,第32是空格,这句话的意思是Cookie value不能有空格,高版本的tomcat不允许有空格。


购物车简单实现

部分代码(利用cookie保存用户浏览记录)

        /**
         * 创建cookie,并发送
         */
        //1.创建cookie
        Cookie cookie = new Cookie("prodHist",createValue(request,id));
        cookie.setMaxAge(1*30*24*60*60);//一个月
        //2.发送cookie
        response.addCookie(cookie);
    }

    /**
     * 生成cookie的值
     * 分析:
     *          当前cookie值                     传入商品id               最终cookie值
     *      null或没有prodHist          1                     1    (算法: 直接返回传入的id )
     *             1                  2                     2,1 (没有重复且小于3个。算法:直接把传入的id放最前面 )
     *             2,1                1                     1,2(有重复且小于3个。算法:去除重复id,把传入的id放最前面 )
     *             3,2,1              2                     2,3,1(有重复且3个。算法:去除重复id,把传入的id放最前面)
     *             3,2,1              4                     4,3,2(没有重复且3个。算法:去最后的id,把传入的id放最前面)
     * @return
     */
    private String createValue(HttpServletRequest request,String id) {

        Cookie[] cookies = request.getCookies();
        String prodHist = null;
        if(cookies!=null){
            for (Cookie cookie : cookies) {
                if(cookie.getName().equals("prodHist")){
                    prodHist = cookie.getValue();
                    break;
                }
            }
        }

        // null或没有prodHist
        if(cookies==null || prodHist==null){
            //直接返回传入的id
            return id;
        }

        // 3,21          2
        //String -> String[] ->  Collection :为了方便判断重复id
        String[] ids = prodHist.split(",");
        Collection colls = Arrays.asList(ids); //<3,21>
        // LinkedList 方便地操作(增删改元素)集合
        // Collection -> LinkedList
        LinkedList list = new LinkedList(colls);


        //不超过3个
        if(list.size()<3){
            //id重复
            if(list.contains(id)){
                //去除重复id,把传入的id放最前面
                list.remove(id);
                list.addFirst(id);
            }else{
                //直接把传入的id放最前面
                list.addFirst(id);
            }
        }else{
            //等于3个
            //id重复
            if(list.contains(id)){
                //去除重复id,把传入的id放最前面
                list.remove(id);
                list.addFirst(id);
            }else{
                //去最后的id,把传入的id放最前面
                list.removeLast();
                list.addFirst(id);
            }
        }

        // LinedList -> String
        StringBuffer sb = new StringBuffer();
        for (Object object : list) {
            sb.append(object+",");
        }
        //去掉最后的逗号
        String result = sb.toString();
        result = result.substring(0, result.length()-1);
        return result;
    }

Session

Cookie的局限:
1)Cookie只能存字符串类型。不能保存对象
2)只能存非中文。
3)1个Cookie的容量不超过4KB。

如果要保存非字符串,超过4kb内容(大部分浏览器的最大值),只能使用session技术。

Session特点:
会话数据保存在服务器端。(内存中)


Session技术核心

HttpSession类:用于保存会话数据

1)创建或得到session对象
HttpSession getSession()
HttpSession getSession(boolean create)

2)设置session对象
void setMaxInactiveInterval(int interval) : 设置session的有效时间
void invalidate() : 销毁session对象
java.lang.String getId() : 得到session编号

3)保存会话数据到session对象
void setAttribute(java.lang.String name, java.lang.Object value) : 保存数据
java.lang.Object getAttribute(java.lang.String name) : 获取数据
void removeAttribute(java.lang.String name) : 清除数据

session也是域对象,和request还有servletContext一样

相较于Cookie,session中的数据可以直接在servlet中传递(域对象的特点),而Cookie必须要先传给浏览器,再从浏览器拿到


Session原理

现象:

s1:session对象

浏览器1:
1)创建session对象,保存会话数据
HttpSession session = request.getSession(); –保存会话数据
浏览器1的新标签页
1)得到session对象的会话数据
HttpSession session = request.getSession(); –可以取出

新的浏览器1(必须是完全关闭后再重启):
1)得到session对象的会话数据
HttpSession session = request.getSession(); –不可以取出

浏览器2:(没有带s001,不能返回s1)
1)得到session对象的会话数据
HttpSession session = request.getSession(); –不可以取出

原理:

代码解读:HttpSession session = request.getSession();(既可以用来创建对象,也可以得到session对象)

1)第一次访问创建session对象,给session对象分配一个唯一的ID,叫JSESSIONID
2)把“JSESSIONID”作为Cookie的Name,value为一个字符串,发送给浏览器保存
3)第二次访问的时候,浏览器带着JSESSIONID的cookie访问服务器
4)服务器得到JSESSIONID,在服务器的内存中搜索是否存放对应编号的session对象。
5)如果找到对应编号的session对象,直接返回该对象
6)如果找不到对应编号的session对象,创建新的session对象,继续走1的流程

JSESSIONID在每个客户端是唯一的,因此会出现上面的现象。


Session细节

1)java.lang.String getId() : 得到session编号
2)两个getSession方法:
getSession(true) / getSession() : 创建或得到session对象。没有匹配的session编号,自动创 建新的session对象。
getSession(false): 得到session对象。没有匹配的session编号,返回null
3)void setMaxInactiveInterval(int interval) : 设置session的有效时间(是指在服务器端的最大时间)
session对象销毁时间:
3.1 默认情况30分服务器自动回收
3.2 修改session回收时间
3.3 全局修改session有效时间

<!-- 修改session全局有效时间:分钟 -->
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>

3.4.手动销毁session对象
void invalidate() : 销毁session对象

4)如何避免浏览器的JSESSIONID的cookie随着浏览器关闭而丢失的问题(那就把Session的ID )

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值