会话与状态 Cookie Session
产生原因:互联网访问 HTTP
HTTP 特点 ------ 无状态的协议
A 访问 index.html 服务器提供了 (服务器不知道这个请求是来自A的)
B 访问 login.html 服务器提供了(服务器也不知道这个请求来自B的)
没有状态 ------ 导致客户端不能进行一系列有身份标识的操作
Cookie和Session 应HTTP无状态性 应互联网而出现的
Cookie是客户端技术 ----- 文本文件
cookie写给用户各自的浏览器
如果存在Cookie 请求中会包含Cookie信息
服务器端可以获得请求中的Cookie
Session是服务器端技术 ----- 服务器端一个Map
服务器端会为每一个浏览器创建单独Session
Session 每个浏览器对应一个,存放数据
Cookie API
1. Cookie 本身具备哪些属性
首先Cookie 是一个 key-value ---- public Cookie(String name,String value)
setValue与getValue方法 ---- 用来存取Cookie对象里面值
setMaxAge与getMaxAge方法(单位:秒) ---- 用来设置和获取Cookie 的存在时长
*当没有设置Cookie时限时,默认不产生Cookie文件
setPath与getPath方法 --- 用来控制在什么请求的情况下使用Cookie
http://localhost:8080/day7/cookie --- 使用这个Servlet创建了一个Cookie path: 当前创建Cookie程序的目录结构 /day7
例如:http://localhost:8080/day7/index.jsp --- 会使用Cookie (请求信息中会包含Cookie 的信息)
http://localhost:8080/day7/aaa/cookie ---- path: /day7/aaa 默认值
例如:http://localhost:8080/day7/index.jsp --- 如果访问资源路径和path不符,请求中不会包含Cookie 信息
http://localhost:8080/day7/bbb/index.jsp ---- 不使用Cookie
setDomain与getDomain方法 --- 用来设置第三方cookie
setDomain(".itcast.cn"); // www.itcast.cn cookie --- 将该cookie 指定为itcast.cn的Cookie
http://localhost:8080/day7/
Cookie
第一方Cookie :访问baidu ,存放了一个baidu的Cookie
第三方Cookie :访问baidu ,存放了Google的Cookie
getName方法 ---- 获得Cookie 名称
2、向客户端写Cookie
resp.addCookie
当没有设置cookie有效期 ----- http响应 Set-Cookie: lastAccessDate="2011-10-30 10:02:30"
如果设置了cookie 有效期 ---- Set-Cookie: lastAccessDate="2011-10-30 10:23:41"; Expires=Sun, 30-Oct-2
3、在服务器端得到客户端Cookie
req.getCookies ----
如果客户端有Cookie了(无论在内存里还是在硬盘里) http请求Cookie: lastAccessDate="2011-10-30 10:02:30"; (path必须一致)
*addCookie 同名覆盖效果!!!!
多个商品 101,102
为什么Session?
Cookie问题,系统登录记住用户名、密码 ---- 密码被放到cookie文件里
Session数据在服务器端!!!!
QQ空间信息放在服务器还是客户端
把QQ空间常用配置写入浏览器Cookie ------ 换一台电脑QQ空间变成默认
把QQ空间配置放到服务器 ---- 配置信息有多大
配置放入内存 还是硬盘
Session信息是放在服务器内存里!!!
API
1、获得Session对象
ServletRequest HttpServletRequest
req.getSession和req.getSession(true)一样
获取session对象,如果对象存在,获得已经存在Session,如果不存在,将创建一个session对象返回
req.getSession(false)
获取session对象,如果对象存在,获得已经存在的session,如果不存在,返回null
HttpSession session = req.getSession(); // 获得session对象
向session存储一个对象
session.setAttribute
读取session一个对象
session.getAttribute
改写最近访问购物车例子,将刚才的存入cookie数据,存入session
Session
浏览器A 访问 服务器端 ---- 会为A创建一个Session对象 ----- JsessionId(32位) 唯一的
服务器端 以Cookie方式 将jsessionid回写给浏览器
下次浏览器在访问服务器时候 自动携带 jsessionid ----- 对应Session对象
手动创建cookie
JSESSIONID=809F9AEA958F03A9A45F25BE619F8488
Set-Cookie: JSESSIONID=51D52440A9422DE2B5832690EC8C10A9; Expires=Sun, 30-Oct-2011 07:24:43 GMT
实现多个浏览器共享一个Session
*win7 IE8
*保持登录状态 第二天 第三天直接登录 ------ Cookie 保存用户名、密码
浏览器Cookie禁用,不只是不能在硬盘中保存cookie而且 在内存中也不能存储Cookie
使用URL重定向来追踪Session
**所有链接、跳转都必须使用URL重写,如果有一个没有重写,那么Session丢了
http://localhost:8080/day7/showProducts;jsessionid=3F031E252D6AB1FE588A6DA618FB7811
Cookie禁用 导致客户端状态丢失,服务器端Session还在
*客户端路径:/day7/session4 ---- req.getContextPath ---> /day7 必须用在JSP或者Servlet里
<%=request.getContextPath() %> ===== /工程名
Cookie和Session的生命周期
Cookie对象由服务器创建的,Cookie会通过resp的addCookie写回浏览器端,如果说你不设置maxAge,那么这个Cookie是一个会话(浏览器打开产生会话,浏览器关闭,终止会话)级Cookie,浏览器关闭,客户端Cookie就消失,如果你设置了maxAge,Cookie会被存储到硬盘上,那么Cookie会在到期后自动删除!服务器端不保存Cookie
Session由服务器端创建,会以一个唯一sessionId标识,session默认存活时间30分钟(如果客户端30分钟内没有访问过Session,那么Session将过期),Session可以设置过期时间
setMaxInactiveInterval(int interval)
Specifies the time, in seconds, between client requests before the servlet container will invalidate this session.
session的销毁
1、过期时自动销毁
2、调用session.invalidate
3、当服务器关闭时
* 客户端是不是通过会话级Cookie来进行与服务器端Session通信,如果想让多个浏览器共享session,手动设定Cookie jsessionid的maxAge
* 如果客户端禁用cookie,服务器端可以通过URL重写来追踪Session
response. encodeRedirectURL(java.lang.String?url)
用于对sendRedirect方法后的url地址进行重写。
response. encodeURL(java.lang.String?url)
用于对表单action和超链接的url地址进行重写
设置Session的失效时间
1、通过web.xml
<session-config>
<session-timeout>10</session-timeout> <!-- 时间的单位是分钟 -->
</session-config>
2、调用Session 的 setMaxInactiveInterval(int interval) 单位秒
默认30分钟不使用,自动销毁
Session失效:session.invalidate --- 常用功能:注销
Session保存一些针对于会话信息
案例一 登陆成功后,将用户的信息存入Session --- 认证、权限
认证: 服务器端知道客户端的身份 ,who are you?
权限:知道了用户的身份后,根据用户的角色,判断用户能做什么
在开发中,增加表单 --- 提交 ---- 数据写入数据库
重复提交:当你网速特别慢
防止重复提交
1、客户端防止 不靠谱!
2、服务器端防止 --- 令牌机制:表单中隐藏标识字段
a. 生成标识字段 // 生成唯一
b. 写入表单隐藏字段
c. 存入Session
java.util.UUID.randomUUID().toString(); 保证生成UUID 一定不重复!!!
<input type="hidden" name="token" value="<%=token %>" />
session.setAttribute("tokenFormSession",token);
当你处理表单后,一定要清除原来的令牌
session.removeAttribute("tokenFromSession");
使用验证码的过程
1、生成一个验证码
2、验证码存入Session --- 生成验证码Servlet中 CheckCodeServlet 存入session
3、表单中显示验证码图片 --- <img src="<%=request.getContextPath() %>/checkCode"/>
4、用户输入验证码,提交表单
5、比较用户提交的验证码是否和session中一样
img.src = img.src; 认为不需重新加载 img.src 已经加载过了
src?uuid 可以的,java的不方便
src?time 时间变的
var img = document.getElementById("checkCodeImg");
var datestr = new Date().getTime();
alert(datestr);
img.src = img.src+"?"+datestr;
第一次访问 /day7/checkCode
第二次 /day7/checkCode?341345213521351
第三次 /day7/checkCode?341345213521351?234132412341
Servlet数据访问范围
request session servletcontext
setAttribute
getAttribute
removeAttrite
三种数据范围区别:
1、可见范围
servletContext 所有servlet共享一个
session 同一个会话可见,写入cookie文件,同一个客户端的不同浏览器共享
request 持有同一个请求对象的servlet共享request中的数据 常结合forward使用
*当你使用resp.sendRedirect可以共享servletcontext、session; 不能共享request数据
2、生命周期
servletcontext 当web服务器启动 出现 当web服务器停止 销毁
session req,getSession 创建 30分钟不使用/服务器停止/调用invalidate时销毁
request 在发生一次http请求时创建,响应结束后 销毁
Servletcontext 一般存放和web应用相关的数据:数据库连接池、线程池、管理员联系方式
session 一般存放和用户相关的数据,不建议存放大规模数据(位于内存中)
request 最最最建议使用一个数据范围,生命周期特短,可以存放大规模数据,*必须在同一次请求中才能共享