cookie
概念
-
是客户端的会话技术,默认cookie是保存在用户的浏览器上
-
程序把用户的数据以cookie的形式写回到用户的浏览器上(响应头:set-cookie)
-
当用户使用浏览器访问程序的时候,携带自己浏览器上的cookie(请求头:cookie)
原理
-
cookie是服务器端创建,客户端保存(默认浏览器的缓存中)
-
cookie是基于http协议的
-
cookie可以在客户端与服务器端传递数据
当浏览器向服务器发送请求,服务根据请求处理后决定是否创建cookie,服务器创建cookie并设置cookie相关的信息(数据.地址.时效),并将其放置到响应头中,发送至浏览器,浏览器解析响应头获取cookie数据进行保存(浏览器允许存储cookie的情况下),当浏览器再次请求服务器时,根据存储时cookie设置的信息(地址:判断是否是设置的地址,,时效:是否过期)判断是否携带cookie,将cookie放置到请求头中,发送给服务器,服务器接收后从请求头中解析cookie数据并使用.
cookie的使用
创建cookie对象并发送至客户端
方法 | 参数 | 备注 |
---|---|---|
new Cookie(name,value); | name:存储cookie的名字 value:存储cookie的值 | name与value都为字符串(最好不要使用中文) |
response.addCookie(c1); | c1:在响应头中添加的cookie对象 | 该方法由响应对象提供 |
@WebServlet(name = "SetCookieServlet", value = "/set") public class SetCookieServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //cookie由服务器创建 存储在客户端浏览器中 //cookie在java中使用Cookie类创建的对象进行表示 //当客户端浏览器请求服务 需要创建cookie时 创建Cookie对象 //cookie只能存储字符串 并每个cookie都是一个键值对 对象 //key与value都是字符串 不建议使用中文 如果使用中文在添加与获取时需要特殊操作 Cookie c1=new Cookie("username","李四"); Cookie c2=new Cookie("password","abcdef"); //cookie通过响应发送至客户端 response.addCookie(c1); response.addCookie(c2); } }
当浏览器请求对应url后,服务器创建cookie对象并响应。
注意:在进行数据传输时会进行流的形式传输,如果数据是中文可能导致乱码问题(所以不建议使用中文作为数据)
客户端获取cookie后进行保存,当再次请求时会携带请求的缓存数据。
获取请求中的cookie数据
方法 | 参数 | 备注 |
---|---|---|
request.getCookies() | 无 | 由request对象提供的获取请求头中cookie数组的方法 |
c.getName() | 无 | 由cookie对象提供的,获取对应cookie对象name的方法 |
c.getValue() | 无 | 由cookie对象提供的,获取对应cookie对象value的方法 |
c.getPath() | 无 | 由cookie对象提供的,获取cookie携带请求url路径 |
c.getMaxAge() | 无 | 由cookie对象提供的,获取cookie的存活时间 |
@WebServlet(name = "GetCookieServlet", value = "/get") public class GetCookieServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //当客户端请求中携带了cookie数据 可以通过请求对象的方法获取cookie数组 Cookie[] cookies = request.getCookies(); //判断cookie是否为null if(cookies!=null){ for (Cookie c:cookies) { //获取name与value System.out.println(c.getName()+"|"+c.getValue()); //因为存储数据的编码与当前环境一致 所以在浏览器显示的中文乱码可以识别 } } } }
cookie中文数据的编码与解码
在进行cookie创建时,如果书写中文,在浏览器存储时可能出现乱码,所以可以先将其转换一定的便后存储,获取后再解码(编码解码只不过是不想将中文直接显示.也可以理解为简单的加密)
-
URLEncoder.encode(“张三”, “UTF-8”);//编码
-
URLDecoder.decode(cookie.getValue(), “UTF-8”);//解码
//在创建cookie添加value时 将数据字符串编码后添加 Cookie c1=new Cookie("username", URLEncoder.encode("张三", "UTF-8") );//编码 //张三编码后=>%E5%BC%A0%E4%B8%89 //在获取cookie后进行解码 输出 URLDecoder.decode(c.getValue(), "UTF-8");//解码
该编码与解码方式使用的是中文在url地址栏进行传输时的编码方式
设置cookie的持久化时间
方法 | 参数 | 备注 |
---|---|---|
c1.setMaxAge(min); | min:设置持久化时间 单位 :秒 | 如果不设置 或设置为任意负数 则为关闭浏览器失效 |
在创建cookie时,可以通过方法设置cookie的持久化时间,如果没有设置默认为-1(任意负数),时间为当前浏览器关闭前(有些浏览器不允许没有进行安全注册(备案)的服务器存储长时间的cookie,但是运行默认cookie的使用)
当关闭浏览器,再次请求时,cookie就会失效,不会携带cookie数据
@WebServlet(name = "SetCookieServlet", value = "/set") public class SetCookieServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //在创建cookie添加value时 将数据字符串编码后添加 Cookie c1=new Cookie("username", URLEncoder.encode("张三", "UTF-8") );//编码 Cookie c2=new Cookie("password","abcdef"); //设置cookie的持久化时间 单位秒 c1.setMaxAge(60*5); //cookie通过响应发送至客户端 response.addCookie(c1); response.addCookie(c2); }
当关闭浏览器 请求获取cookie地址,由于只设置了username的存活时间,所以password设置为默认浏览器关闭失效,所以重新打开浏览器请求只有username
设置cookie的访问路径
当创建cookie时可以设置cookie的访问路径(当前请求服务器对应路径时才会携带cookie,请求其他路径不会携带cookie)
方法 | 参数 | 备注 |
---|---|---|
c1.setPath(url); | url:设置请求的路径 | 如果没有设置则当前服务器任意url都携带cookie |
//设置cookie访问路径 //只有请求当前服务器并且访问路径为指定路径时才携带cookie //如果没有设置 默认为/ 请求当前服务器任意路径都会携带cookie c1.setPath("/get");
由于username设置了请求的url为get 所以请求set路径时不会携带cookie
由于设置了项目名称,所以请求的url前需要书写项目名称,所以uername还是不会携带
当直接请求服务器地址/get时,就会携带对应的cookie
//cookie常用的path设置路径 //1.默认路径/ //只要请求的是当前的服务器 都会携带cookie(默认) c1.setPath("/"); //2.项目路径 /项目名 //只要请求的url是指定项目下的url 都会携带cookie c1.setPath("/web0816") //3.服务路径 /项目名/服务名 //只有请求指定服务时 才会携带cookie c1.setPath("/web0816/get")
删除cookie
cookie由服务器创建存储在客户端浏览器,所以不能通过方法直接删除,但是可以通过设置cookie的存活时间进行删除,也可以将value设置为空字符串
//清除Cookie Cookie cookie = new Cookie("username", ""); //1:设置访问的路径path, 这里的Path必须和设置Cookie 的路径保持一致 cookie.setPath(request.getContextPath()); //2:设置存活时间 cookie.setMaxAge(0); //3:将cookie发送到浏览器 response.addCookie(cookie); //删除cookie就是将指定cookie存活时间设置为0让浏览器删除
案例
显示上一次访问时间
package com.yh; import java.io.IOException; import java.text.SimpleDateFormat; 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 LastTimeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //通过request获取所有的cookie Cookie [] cks = req.getCookies(); //定义cookie变量 Cookie c = null; //判断cks是否为空 if(cks != null){ //遍历数组 for (Cookie cookie : cks) { //查找名字是lasttime的cookie if(cookie.getName().equals("lasttime")){ //找到了 c = cookie; break; } } } //获取系统当前时间 Date date = new Date(); //判断c是否为空 if(c == null){ //用户是第一次访问 c = new Cookie("lasttime", Long.toString(date.getTime())); //向客户端响应你好 resp.getWriter().write("Hello"); }else{ //用户不是第一次访问 String lasttime = c.getValue(); //日期解析 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String now = df.format(new Date(new Long(lasttime))); //响应到客户端 resp.getWriter().write("你好上一次访问的时间是"+now); c.setMaxAge(10); //将当前系统时间写入到cookie中 c.setValue(Long.toString(date.getTime())); } //将cookie写回浏览器 resp.addCookie(c); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
显示用户浏览历史记录
product_list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <style type="text/css"> img{ width:200px; } </style> </head> <body> <h2>商品列表</h2> <div> <a href="/huihua/historyServlet?pid=1"><img alt="" src="./image/1.jpg"></a> </div> <div> <a href="/huihua/historyServlet?pid=2"><img alt="" src="./image/2.jpg"></a> </div> <div> <a href="/huihua/historyServlet?pid=3"><img alt="" src="./image/3.jpg"></a> </div> <div> <a href="/huihua/historyServlet?pid=4"><img alt="" src="./image/4.jpg"></a> </div> <h2>历史浏览记录</h2> <% Cookie [] ck = request.getCookies(); if(ck != null){ for(Cookie cookie : ck){ if(cookie.getName().equals("history")){ String lishi = cookie.getValue(); String [] goodsId = lishi.split("-"); for(int i = 0;i<goodsId.length;i++){ %> <img alt="" src="./image/<%=goodsId[i] %>.jpg"> <% } } } } %> </body> </html>
HistoryServlet.java
package com.yh; 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; public class HistoryServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取商品pid String pid = req.getParameter("pid"); //获取客户端发送的cookie Cookie[] cks = req.getCookies(); //定义cookie Cookie cookie = null; //判断cks是否为空 if(cks != null){ //遍历数组,查找历史纪录的cookie for (Cookie c : cks) { if(c.getName().equals("history")){ //历史纪录的cookie已经存在 cookie = c; } } } if(cookie == null){ //新建历史纪录cookie "1-2-3-" cookie = new Cookie("history", pid+"-"); }else{ //获取cookie的值 String lishi = cookie.getValue(); //将字符串转StringBuilder StringBuilder sb = new StringBuilder(lishi); //在字符串中查找pid if(sb.indexOf(pid) != -1){ //找到了 }else{ //没找到 sb.insert(0, pid+"-"); } lishi = sb.toString(); cookie.setValue(lishi); } //写回浏览器 resp.addCookie(cookie); //重定向商品列表 resp.sendRedirect("/huihua/product_list.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }