Cookie
Cookie简介
Cookie是Servlet向Web服务器发送的一些少量信息,这些信息由浏览器保存,然后发送回服务器。Cookie一般用来保存会话ID来实现会话跟踪(jsessionid=xxxxxxxxx)
一个Cookie拥有一个名称、一个值和一些可选的属性,比如注释、路径和域限定符、最大生存时间和版本号。
Servlet通过使用HttpServletResponse的addCookie(cookie)方法将Cookie发送到浏览器,该方法将字段添加到HTTP响应头发送到浏览器。浏览器支持每台Web服务器有20个Cookie,总共有30个Cookie,每个Cookie的大小默认为4kB。
浏览器通过向HTTP请求头添加字段将Cookie返回给Servlet。可使用HTTPServletRequest的getCookies()方法从请求中获取Cookie。
Cookie通过路径和名称来进行区分,可以参考我的另一篇文章:Cookie的作用域。
Cookie常用方法
Cookie(String name, String value):构建通过key/value保存信息(注意都是String类型)。
void setDomain(String pattern):指定应在其中显示此Cookie的域。
String getDomain():返回此Cookie设置的域名。
void setMaxAge(int expiry):设置Cookie的最大生存时间,以秒为单位。负值表示浏览器退出时删除,0值则会导致立马删除Cookie。
int getMaxAge():返回以秒为单位指定的Cookie的最大生存时间。
String getName():返回Cookie的名称。名称在创建之后不得更改,否则将被覆盖。
String getValue():返回Cookie的值。
void setPath(String uri):指定客户端应该返回Cookie的路径。对于指定目录中的所有页面以及该目录子目录中的所有页面都是可见的。
使用Cookie
在服务器端添加Cookie
在服务器端获取Cookie
删除Cookie
客户端禁用Cookie
程序示例
工程名称:SessionTrack
HTML文件(cookietest.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>
<a href="save">保存Cookie</a>
</p>
<p>
<a href="temp/read">读取Cookie</a>
</p>
<p>
<a href="remove">移除Cookie</a>
</p>
</body>
</html>
保存Cookie(SaveCookieServlet.java)
package com.li.servlet.cookie;
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 SaveCookieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie c1=new Cookie("test1", "test1value");
resp.addCookie(c1);
//不设置路径表示cookie的路径在我们当前的Servlet配置路径下
Cookie c2=new Cookie("test2", "test2value");
//这个斜杠表示我们当前工程的根目录,表示任意应用都可以访问
c2.setPath("/");
resp.addCookie(c2);
Cookie c3=new Cookie("test3", "test3value");
//这个斜杠表示我们当前工程的根目录下的temp文件下,只对该目录及其子目录可见
c3.setPath("/SessionTrack/temp/");
resp.addCookie(c3);
/*保存到Cookie我们也可以在浏览器中查看,并查看其值*/
resp.sendRedirect("cookietest.html");
}
}
读取Cookie(ReadCookieServlet.java)
package com.li.servlet.cookie;
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 ReadCookieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
//获取所有Cookie数组(之前的第三个Cookie获取不到,因为路径不同)
//要想读取第三个Cookie,需要将服务配置到Cookie的可见目录下(web.xml)
Cookie[] cookies=req.getCookies();
StringBuilder sb=new StringBuilder("<h3>Cookie信息:</h3>");
for (Cookie c : cookies) {
sb.append("<li>").append(c.getName()).append("->").append(c.getValue()).append("</li>");
}
//设置内容类型
resp.setContentType("text/html; charset=UTF-8");
resp.getWriter().write(sb.toString());
}
}
移除Cookie(RemoveCookieServlet.java)
package com.li.servlet.cookie;
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;
/*通过更改生命周期的方式来删除Cookie*/
public class RemoveCookieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//删除保存到c1Cookie,设置生存时间为零秒即可
//name值只有一个,新建相同name的cookie相当于更新
Cookie c1=new Cookie("test1", "test1value");
c1.setMaxAge(0);
resp.addCookie(c1);
resp.sendRedirect("cookietest.html");
}
}
配置文件(web.xml)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>SessionTrack</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<!-- Cookie配置 -->
<servlet>
<servlet-name>SaveCookie</servlet-name>
<servlet-class>com.li.servlet.cookie.SaveCookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SaveCookie</servlet-name>
<url-pattern>/save</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ReadCookie</servlet-name>
<servlet-class>com.li.servlet.cookie.ReadCookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ReadCookie</servlet-name>
<url-pattern>/temp/read</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>RemoveCookie</servlet-name>
<servlet-class>com.li.servlet.cookie.RemoveCookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RemoveCookie</servlet-name>
<url-pattern>/remove</url-pattern>
</servlet-mapping>
</web-app>
URL重写
为什么要对URL进行重写?
客户端不支持Cookie或者禁用Cookie。
服务器端不能通过Cookie获取jsessionid
URL重写
将jsessionid加入到URL之后。
使用HttpServletResponse重写
String encodeURL(String URL):通过将会话ID包含在指定URL中并对该URL进行编码。如果不需要编码,则返回未更改的URL。
String encodeRedrectURL(String url):对指定的URL进行编码,以便在sendRedirect方法中使用它,如果不需要编码,则返回未更改的URL(可判断是否需要将ID加入URL)
程序示例
请参考我的另一篇博客:HttpSession
这里有我使用session验证登录的程序,下面的程序只是对这个程序做了一些更改。
对于我们用session来验证登录的程序,如果我们在浏览器禁用Cookie,那我们便永远通过session来访问服务,会一直出现在登录页面
验证登录(LoginServlet)
通过重写URL,当我们登录时,我们把鼠标悬在返回首页的链接上,可以发现,jsessionid被加载链接的URL后面。
package com.li.servlet;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/pages/login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String name=req.getParameter("name");
String password=req.getParameter("password");
if("admin".equals(name) && "123456".equals(password)) {
//获取会话
HttpSession session=req.getSession();
session.setAttribute("uesr", name);
resp.setContentType("text/html;charset=UTF-8");
/*URL重写,解析出重写的部分*/
String encodeURL="";
Pattern pattern = Pattern.compile(";\\S+");
Matcher m = pattern.matcher(resp.encodeURL("../index.jsp"));
while(m.find()) {
encodeURL=m.group();
}
/*放入ServletContext中,在EL表达式通过applicationScope域获取*/
getServletContext().setAttribute("encodeURL", encodeURL);
resp.getWriter().write("<strong>欢迎"+name+"!</strong><br/><a href='"+resp.encodeURL("../index.jsp")+"'>返回首页</a>");
}
else {
/*由于我们在配置文件中已经把服务配置到pages文件下,
*所以,此处我们使用的是相对路径,不在需要加重定向位置所在的文件夹。
*/
resp.sendRedirect("login.html");
}
}
}
主页HTML(index.jsp)
<%@ page pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>
<a href="pages/login.html">登录</a>
</p>
<p>
<a href="test${applicationScope.encodeURL }">访问TestServlet(需要登录之后才能访问)</a>
</p>
<p>${applicationScope.url }</p>
</body>
</html>
TestServlet服务程序(TestServlet.java)
此程序并未做任何修改
package com.li.servlet;
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 TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//注意参数,session可以为null, 也可以不使用参数从而判断session是否为新的
HttpSession session=req.getSession(false);
if(session==null || session.getAttribute("uesr")==null) {
resp.sendRedirect("../pages/login.html");
//System.out.println(getContextPath());
}
else {
resp.setContentType("text/html; charset=UTF-8");
resp.getWriter().write("<h3>欢迎"+session.getAttribute("uesr")+"访问TestServelt</h3><a href='../index.html'>返回首页</a>");
}
}
}