关于cookie机制你只需要知道这些
1. cookie是由服务器端生成的,并且可以对cookie进行基本的操作
2. 浏览器能够识别服务器端传输过来的cookie,并存储服务器端传输过来的cookie
3. 浏览器的每次请求都会携带cookie回服务器,服务器能够识别浏览器请求携带过来的cookie,且能够在响应中携带这些cookie返回给浏览器
4. 服务器端的会话状态是由session实现的,而session是由cookie去定位。每一个会话对应一个session,每一个session对应一个id,而每个id对应一个名为JSESSIONID的cookie(是的,cookie有名字,cookie的name就是cookie的key,是cookie的唯一标识),有了cookie机制才有了session机制
创建cookie
//创建cookie
Cookie cookie = new Cookie(cookieName, cookieValue);
Cookie只有一个有参构造方法,所以在创建cookie时必须指定cookie的名称和所对应的值
上图就是我访问百度时,百度服务器创建并返回给浏览器的cookie,可以看出百度的服务器创建了很多不同用途的cookie
设置cookie的生命周期
//设置cookie的路径
cookie.setMaxAge(-1);
数字 | 解释 |
---|---|
-1 | cookie的生命周期受浏览器窗口限制,浏览器窗口不关闭cookie就一直存在,窗口关闭,cookie销毁 |
0 | 浏览器接收到cookie的那一刻就立即销毁了cookie,因为生命时长只有0秒 |
3600 | 不管浏览器关闭多少次,cookie会存在3600s,即一小时整,时间一到即销毁cookie |
设置cookie的域
//设置cookie的域
cookie.setDomain(domainName);
设置cookie的域并不是必要的,但在需要解决cookie跨域问题的项目里就是必要的。默认不设置的情况下,cookie的域为当前访问的域名,服务器只能获取域为当前域及其父域下的cookie,下面举几个详细的对比案例,✘为接收不到cookie,✔️为能接收到cookie
1.访问zaomianbao.com
操作 | zaomianbao.com | blog.zaomianbao.com | test.blog.zaomianbao.com |
---|---|---|---|
不设置 | ✔️ | ✔️ | ✔️ |
cookie.setDomain(“.zaomianbao.com”) | ✔️ | ✔️ | ✔️ |
cookie.setDomain(“.blog.zaomianbao.com”) | ✘ | ✔️ | ✔️ |
cookie.setDomain(“.test.blog.zaomianbao.com”) | ✘ | ✘ | ✔️ |
2.访问blog.zaomianbao.com
操作 | zaomianbao.com | blog.zaomianbao.com | test.blog.zaomianbao.com |
---|---|---|---|
不设置 | ✘ | ✔️ | ✔️ |
cookie.setDomain(“.zaomianbao.com”) | ✔️ | ✔️ | ✔️ |
cookie.setDomain(“.blog.zaomianbao.com”) | ✘ | ✔️ | ✔️ |
cookie.setDomain(“.test.blog.zaomianbao.com”) | ✘ | ✘ | ✔️ |
3.访问test.blog.zaomianbao.com
操作 | zaomianbao.com | blog.zaomianbao.com | test.blog.zaomianbao.com |
---|---|---|---|
不设置 | ✘ | ✘ | ✔️ |
cookie.setDomain(“.zaomianbao.com”) | ✔️ | ✔️ | ✔️ |
cookie.setDomain(“.blog.zaomianbao.com”) | ✘ | ✔️ | ✔️ |
cookie.setDomain(“.test.blog.zaomianbao.com”) | ✘ | ✘ | ✔️ |
注:设置域名前面带点是规范,RFC2109中提到:The value for the Domain attribute contains no embedded dots or does not start with a dot,即cookie的domain的值,必须是以点开始的,不以点开始的cookie,应该拒绝丢弃。(如果不严格,不带点也可以)
设置cookie的路径
//设置cookie的路径
cookie.setPath("/");
cookie的path默认是当前我们访问的页面,那么当设置为”/”时即为cookie在同一个应用下共享。总结就是:domain决定在哪个域下共享,path决定在哪个路径下共享。
将cookie传给浏览器
//将创建的cookie放入HttpServletResponse中响应回浏览器
response.addCookie(cookie);
将服务器创建的cookie放入response中,服务器的响应就会携带添加进来的cookie返回给浏览器
服务器获取请求中的cookie
//获取请求中携带过来的cookie
Cookie[] cookieList = request.getCookies();
当浏览器再次访问我们应用下的页面是,就会再次发送请求给我们的服务器,那么服务器就可以通过以上方法获得当前domain以及父domain的cookie
删除cookie
//cookie没有删除方法,只有通过控制生命周期为0间接销毁浏览器上存储的对应的cookie
cookie.setMaxAge(0);
response.addCookie(cookie);
下面提供一个操作cookie的工具类
package util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* descri: cookie工具类
* author: LiuChengxiang
*/
public class CookieUtil {
/**
* 获取cookie
*/
public static String getCookie(HttpServletRequest request, String cookieName, String encodeString) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null) {
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
break;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return retValue;
}
/**
* 创建并设置cookie
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response,String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
try {
if (cookieValue == null) {
cookieValue = "";
} else {
cookieValue = URLEncoder.encode(cookieValue, encodeString);
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0)
cookie.setMaxAge(cookieMaxage);
if (null != request) {
String domainName = getDomainName(request);
System.out.println(domainName);
if (!"localhost".equals(domainName)) {
cookie.setDomain(domainName);
}
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取域名
*/
private static String getDomainName(HttpServletRequest request) {
String domainName = null;
String serverName = request.getRequestURL().toString();
if (serverName == null || serverName.equals("")) {
domainName = "";
} else {
serverName = serverName.toLowerCase();
serverName = serverName.substring(7);
int end = serverName.indexOf("/");
serverName = serverName.substring(0, end);
String[] domains = serverName.split("\\.");
int len = domains.length;
if (len > 3) {
domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
} else if (len < 4 && len > 1) {
domainName = "." + domains[len - 2] + "." + domains[len - 1];
} else {
domainName = serverName;
}
if(isNumeric(domains[len-1])){
domainName = serverName;
}
}
if (domainName != null && domainName.indexOf(":") > 0) {
String[] ary = domainName.split("\\:");
domainName = ary[0];
}
return domainName;
}
/**
* 判断数字
*/
private static boolean isNumeric(String str){
for (int i = str.length();--i>=0;){
if (!Character.isDigit(str.charAt(i))){
return false;
}
}
return true;
}
}
如有错误,评论区下指正