HTTP是无状态协议,为了解决记录通信过程中的状态数据的需求可以使用Cookie机制或者Session机制。
状态管理:将浏览器与web服务器之间多次交互所涉及的数据保存下来
保存方式:保存在客户端(Cookie)/保存在服务器端(Session)
(1)Cookie
1)Cookie:浏览器在访问服务器时,服务器会将少量的数据(大约4K左右)以set-cookie消息头的方式发送给浏览器,浏览器会将这些数据保存下来(内存或硬盘)。浏览器再次访问服务器时,会将之前保存的这些数据以cookie消息头的方式发送给服务器。
2)创建Cookie
step1 创建一个Cookie对象
Cookie c = new Cookie(String name, String value);
step2 添加到response对象
response.addCookie(c);
3)查询Cookie
Cookie[] request.getCookies(); //该方法有可能返回null
String cookie.getName();
String cookie.getValue();
4)编码问题
cookie只能保存ascii字符,如果出现非ascii字符,需要将其转换成ascii字符的表示形式。可以使用
编码:String URLEncoder.encode(String str, String enc)
解码:String URLDecoder.decode(String str, String enc)
5)生存时间
cookie.setMaxAge(int seconds);
*当seconds > 0时,浏览器会将cookie保存在硬盘上,超过指定时间删除cookie
seconds < 0时,浏览器会将cookie保存在内存中,只要浏览器关闭,cookie就被删除
seconds = 0时,浏览器会立即删除cookie
6)删除一个cookie
Cookie c = new Cookie("somecookie", "");
c.setMaxAge(0);
response.addCookie(c);
7)cookie的路径问题
浏览器在访问服务器的时候,并不会将所有的cookie全部发送给服务器,而是比较服务器的地址与cookie的地址是否匹配(要访问的服务器的地址是cookie地址或者是cookie地址的子路径),只有符合要求的cookie才会发送。
在默认情况下,cookie的路径(cookie地址)等于添加该cookie的组件的路径。
比如:/WebDemo/jsp01/addCookie.jsp添加了一个cookie,则该cookie的路径为/WebDemo/jsp01
*通过调用cookie.setPath("/appname")可以设置cookie地址
8)一般情况下添加一个cookie的步骤:
Cookie cookie = new Cookie("username", URLEncoder.encode("张三", "utf-8");
cookie.setMaxAge(1000);
cookie.setPath("/WebDemo");
request.addCookie(c);
8)cookie的缺点:
a. 浏览器可以禁止
b. 不安全
c. cookie能够保存的数据大小有限制,只能保存少量的数据(4k)
d. cookie的个数也有限制,大约300个
CookieUtil:
public class CookieUtil { public static int age = 3600 * 24; public static void addCookie(String name, String value, int age, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException { Cookie c = new Cookie(name, URLEncoder.encode(value, "utf-8")); c.setMaxAge(age); c.setPath(request.getContextPath()); response.addCookie(c); } public static void addCookie(String name, String value, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException { addCookie(name, value, age, request, response); } public static String findCookie(String name, HttpServletRequest request) throws UnsupportedEncodingException { String value = null; Cookie[] cookies = request.getCookies(); if(cookies != null) { for(int i = 0; i < cookies.length; i++) { Cookie cur = cookies[i]; if(cur.getName().equals(name)) { value = URLDecoder.decode(cur.getValue(), "utf-8"); } } } return value; } public static void delete(String name, HttpServletResponse response) { Cookie c = new Cookie(name, ""); c.setMaxAge(0); response.addCookie(c); } }
(2)Session
1)什么是session
当浏览器访问服务器时,服务器会创建一个对象(一般称之为session对象,该对象有一个sessionId,是唯一的),然后将这个sessionId发送给浏览器(默认情况下使用cookie机制发送)。浏览器会将sessionId保存下来,当浏览器再次访问服务器时会将seesionId发送给服务器。服务器依据sessionId就可以找到之前创建好的session对象。
2)获得一个session对象
a. HttpSession s1 = request.getSession(boolean flag);
当flag = true时,
服务器检查请求当中是否有sessionId,如果没有则创建一个session对象。如果有sessionId,会依据sessionId查找对应的session对象,如果找到了则返回;如果找不到(比如session超时,服务器已经将之前创建的session对象删除),则创建一个新的session对象。
当flag = false时,
服务器检查请求当中是否有sessionId,如果没有则返回null。如果有sessionId,会依据sessionId查找对应的session对象,如果找到了则返回;如果找不到则返回null。
b. HttpSession s2 = request.getSession();
等价于request.getSession(true);
3)session的几个常用方法
String session.getId();
session.setAttribute(String name, Object obj);
Object session.getAttribute(String name);
session.removeAttribute(String name);
4)session超时
容器会将空闲时间过长的session对象从内存里删除掉(为了节省内存空间)。
大部分容器的缺省时间是30分钟。
可以修改服务器缺省的超时时间限制:
比如tomcat可以修改$CATALINA_HOME/conf/web.xml中
<session-config>
<session-timeout>30</session-timeout>
</session-config>
修改后需要重启服务器
也可以修改某个应用的web.xml
另外,session.setMaxInactiveInterval(int seconds);
5)session删除
session.invalidate();
6)案例
a. session验证
step1 在登录成功之后,将一些数据绑定到session对象上
比如: session.setAttribute("user", user);
step2 对于需要保护的资源(只有登录成功以后才能访问的地址),添加session验证代码。
比如:
Object obj = session.getAttribute("user");
if(obj == null) {
// 没有登录
response.sendRedirect("login.jsp");
}
b. 验证码
c. 购物车
7)当用户禁止cookie后,如何使用session
可以使用url重写机制
url重写:在访问某个组件时,不直接使用其地址,而是使用包含了服务器生成的sessionId的地址。
链接地址、表单提交地址使用response.encodeURL(String url)进行处理。
重定向地址使用response.encodeRedirectURL(String url)进行处理。
8)session的优缺点
跟cookie比,session相对来讲会更安全,保存的数据大小从理论上没有限制,保存的数据类型更丰富。
session是一种服务器端状态管理技术,会将所有的状态保存在服务器端,所以服务器的数据压力会更大(服务器可以将session中的数据临时保存到数据库或者硬盘上)。
*有时候需要同时使用session和cookie一起来解决比较复杂的状态管理问题