Cookie翻译成中文是小甜点,小饼干的意思。在HTTP中它表示服务器送给客户端浏览器的小甜点。其实Cookie就是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。
你大可以放心,Cookie不会占满你的硬盘。因为一个Cookie最多只有4KB,并且浏览器最多可以保存300个Cookie。当然,在浏览器大战的今天,一些浏览器为了打败对手,可能对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等!但也不会出现把你硬盘占满的可能!
不同的浏览器之间不能共享Cookie!!!
Cookie的作用可大了,但无论怎么夸大Cookie的作用都离不开“跟踪客户端状态”这句话。我们知道Cookie是服务器保存在客户端的信息,然后客户端会在下次请求时把Cookie在还给服务器,这样服务器就可以通过信息来识别客户端了。
这是响应工作的一部分,所以这个方法是response对象的。并且Cookie是HTTP协议中的内容,所以保存Cookie是HttpServletResponse类的方法。
void addCookie(Cookie c): 添加Cookie对象到当前response对象中,这个方法可以被调用多次,从而完成添加多个Cookie对象到response中。
Cookie cookie = new Cookie("username", "txjava"); response.addCookie(cookie);通过浏览器的开发者工具我们可以看到,该请求的响应头中被添加了Set-Cookie的值: 同样根据浏览器的开发者工具我们可以看到http://localhost:8080的网址的cookie中被加入了username=txjava的信息: 这时我们再对服务器进行访问就会发现,访问服务器时请求时带着cookie的值的:
我们现在已经可以保存Cookie到客户端了,但还没有学习让服务器如何读取Cookie。
如果浏览器保存了Cookie,那么会在下一次请求时把Cookie放到请求头中发送给服务器,这时服务器需要在请求中读取Cookie。既然是在请求中读取,那么当然是使用request对象来读取了。
HttpServletRequest:Cookie[] getCookies()
示例:
Cookie[] cookies = request.getCookies(); if(cookies != null){ for(Cookie cookie : cookies){ System.out.println(cookie.getName() +":"+ cookie.getValue()); } }Cookie会在客户端存活多久呢?这就是Cookie的生命了。默认情况下,Cookie只在浏览器的内存中存活,也就是说,当你关闭浏览器后,Cookie就会消失!
可以使用cookie.setMaxAge(int expiry)来设置Cookie的存活时间。参数expiry表示Cookie存活的秒数。
cookie.setMaxAge(60*60): 表示cookie对象可存活1小时。就算关闭浏览器,就算重启客户端电脑,cookie也会存活1小时。因为当maxAge大于0时,浏览器不仅会把cookie保存在浏览器内存中,还会把cookie保存到硬盘上。cookie.setMaxAge(-1): cookie的maxAge属性的默认值就是-1(其实只要是负数都是一个意思),表示只在浏览器内存中存活。一旦关闭浏览器窗口,那么cookie就会消失。cookie.setMaxAge(0): cookie被作废!表示cookie即不在内存中存活,也不在硬盘上存活,这样的cookie设置只有一个目的,那就是覆盖客户端原来的这个cookie,使其作废。设置-隐私设置和安全性-清除浏览数据:
选项 - 隐私与安全 - Cookie和网站数据 - 清除数据
Cookie还有一个path属性,可以通过Cookie#setPath(String)方法来设置。你可以使用HttpWatch查看响应中的Set-Cookie中是否存在路径。下面是通过Chrome查看Cookie信息。 也就是说,就算你不设置Cookie的path,Cookie也是有路径的。这个路径就是请求的路径。
例如:
在请求:http://localhost:8080/cookie_demo/path 时,服务器响应了一个Cookie,那么这个Cookie的默认路径就是/cookie_demo。如果是在请求:http://localhost:8080/cookie_demo/path/son 时,服务器响应了一个Cookie,那么这个Cookie的默认路径就是/cookie_demo/path。到现在我们还没说过Cookie的path有什么用,现在我们来聊聊path的作用。首先声明一点,path不是指Cookie在客户端存放的路径!!!不同的浏览器存放Cookie的路径是不同的!!!你不能通过Cookie的path来指定Cookie文件的存放路径!!!
那么Cookie的path是干什么的呢?假设你的浏览器当前已经有了两个Cookie:
cookie1:name=path1;value=pathvalue1;path=/cookie_demo;cookie2:name=path1;value=pathvalue2;path=/cookie_demo/path;当访问http://localhost:8080/cookie_demo/*时,请求头中会包含cookie1,而不会包含cookie2。 当访问http://localhost:8080/cookie_demo/path/*时,请求头中会包含cookie1和cookie2。
也就是说,在访问子路径时,会包含其父路径的Cookie,而在访问父路径时,不包含子路径的Cookie。
如果你想在BServlet中设置的Cookie,在客户端访问AServlet时也包含在请求头中,那么就需要设置BServlet中的Cookie的path:
c2.setPath(“/cookie_demo”):硬编码;c2.setPath(request.getContextpath() + “/”):活编码。这样就可以设置Cookie的路径,保存在访问AServlet时,也会包含BServlet中添加的Cookie。
Cookie的SetPath设置cookie的路径,这个路径直接决定服务器的请求是否会从浏览器中加载某些cookie。
首先默认情况如果不设置cookie的path,默认是 /项目名称/当前路径的上一层地址 例如:
请求路径:/cookie_demo/servlet/logincookie的路径:/cookie_demo/servlet如果我们设置path,如果当前访问的路径包含了cookie的路径(当前访问路径在cookie路径基础上要比cookie的范围小)cookie就会加载到request对象之中。
Cookie中保存中文,次要。
Cookie中是不可以设置中文的,但可以使用URLEncodor.encode()方法编码后在存放到Cookie中。在获取Cookie时,需要先使用URLDecoder.decode()方法解码,再使用。
添加cookie:
Cookie cookie1 = new Cookie("username", URLEncoder.encode(username,"UTF-8"));读取cookie:
Cookie[] cookies = request.getCookies(); if(cookies != null){ for(Cookie cookie : cookies){ if(cookie.getName().equals("username")) username = URLDecoder.decode(cookie.getValue(),"UTF-8"); if(cookie.getName().equals("password")) password = cookie.getValue(); } }默认情况下浏览器的cookie是被启用的,但是其实我们是可以手动的禁用cookie的,强烈不建议禁用cookie; Cookie一旦被禁用掉绝大多数互联网的网站都无法登录,这个跟我们后续要讲解的session有关。
那么我们如何通过程序来通过程序判断用户的浏览器上的cookie是否被禁用了呢,其实很简单,我们可以通过去刚刚添加的cookie,如果没有取到,说明cookie被禁用。
我们都知道HTTP是无状态协议,但是为什么session可以跟踪会话状态呢?没错,session依赖Cookie。
当客户端第一次访问服务器时,服务器会为客户端创建一个session对象,然后把session对象放到session池中,在响应时把sessionId通过Cookie响应给客户端。注意,只有在第一次访问时,服务器才会创建session,给客户端响应sessionId。从此以后就不会了!
当客户端再次访问服务器时,会在请求中带着sessionId给服务器,服务器通过sessionId到session池中找到session对象,这就可以完成会话跟踪了。也就是说,服务器端保存的是session对象,而客户端只有sessionId。每次访问都需要通过客户端的sessionId来匹配服务器端的session对象!这样用户在session中保存的数据就可以再次被使用了。
sessionId是服务器通过Cookie发送给客户端浏览器的,这个Cookie的maxAge为-1,即只在浏览器内存中存在。如果你关闭所有浏览器窗口,那么这个Cookie就会消失了!
session失效有如下几个原因:
session.invalidate()方法注销sessionsession超时 <session-config> <!-- session的超时时间,以分钟为单位 --> <session-timeout>1</session-timeout> </session-config> Cookie被禁用使用cookie实现自动登陆
html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="login" method="post"> 用户:<input type="text" name="username"/><br> 密码:<input type="password" name="password"/><br> <input type="checkbox" value="1" name="auto"/> 一天内自动登陆<br> <input type="submit" value="登陆"/> </form> </body> </html>Java代码:
package cn.tx.servlet; import cn.tx.model.User; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; /** * 模拟自动登陆方法 */ @WebServlet(name = "LoginServlet",urlPatterns = "/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取用户端提交的表单信息 String username = request.getParameter("username"); String password = request.getParameter("password"); String auto = request.getParameter("auto"); // 统一设置response响应格式及编码 response.setContentType("text/html;charset=utf-8"); response.setCharacterEncoding("UTF-8"); // 判断是否提交用户信息 if(username == null && password == null && auto == null){ // 用来接收cookie的value信息 String cookieValue = null; // 获取用户端cookies Cookie[] cookies = request.getCookies(); // 如果cookies不为null 尝试获取name为txjavac的cookie的value if(cookies != null){ for(Cookie ck : cookies){ if(ck.getName().equals("txjavac")){ cookieValue = ck.getValue(); } } } // 如果没有获取到cookie的value 返回信息 if(cookieValue == null){ response.getWriter().write("您还未进行登陆,请进行登陆!!!"); return; }else{// 如果获取到 // 对该信息进行解码 BASE64Decoder decoder = new BASE64Decoder(); cookieValue = new String(decoder.decodeBuffer(cookieValue)); // 对解码后的字符串进行切分 String[] split = cookieValue.split(":"); // 获取用户名和密码 username = split[1]; password = split[2]; // 创建用户对象 User user = new User(username,password); // 获取session HttpSession session = request.getSession(); // 把用户对象存储到session中 session.setAttribute("user",user); // 返回内容 response.getWriter().write("尊敬的"+username+",欢迎您来到拓薪教育!!!"); return; } } // 判断用户名或密码是否正确 if(username!=null && password!=null && username.equals("admin") && password.equals("txjava")){ // 创建用户对象 User user = new User(username,password); // 获取session会话对象 HttpSession session = request.getSession(); // 把用户存入session中 session.setAttribute("user",user); // 用户名密码正确的话,判断是否勾选了一天内自动登陆 if(auto != null && auto.equals("1")){ // 拼接存储于cookie的value值 String value = "txjava:" + username + ":" + password + ":" + 24*3600; // 进行BASE64编码 BASE64Encoder encoder = new BASE64Encoder(); value = encoder.encode(value.getBytes()); // 创建cookie并且设置一天失效后添加到response Cookie cookie = new Cookie("txjavac",value); cookie.setMaxAge(24*3600); response.addCookie(cookie); } response.getWriter().write("尊敬的"+username+",欢迎您来到拓薪教育!!!"); return; }else { response.getWriter().write("用户名或密码错误!!!"); return; } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } }