|
该用户从未签到
|
状态管理' j6 n; J' b% o. ^/ [
1)什么是状态管理# Y' _- N5 L1 Q; ]* g2 I
将客户端(一般是浏览器)与服务器之间的多次
5 i0 M$ Q) f" ^; c& K$ z 交互当作一个整体来看待,即将多次操作所涉及的9 W7 a; j9 |5 F$ o# z- {
数据记录下来。; F9 Q' E' U* [: d' t1 p
2)怎样进行状态管理# N- d- P% \- a9 k( T
第一种方式,在客户端管理用户的状态 J# l+ B) g' O Z
(cookie)。9 O( s! u& K( ?- ^$ W
第二种方式,在服务器端管理用户的状态
! ~' T2 Q1 b0 g" w) h- B& R- [# S (session)。
1 L. V0 i, \+ N( J 3)cookie9 g) s2 j+ O2 {8 R& O$ R% A
a,什么是cookie?
$ V% A8 K% Z) x( R' y 浏览器在访问服务器时,服务器将一些数据, r+ }1 l. @: C% H7 R9 J
以set-cookie消息头的形式发送给浏览器。浏览
1 T. Z& c( U# c 器会将这些数据保存起来。当浏览器再次访问
" \' _8 X/ i( v) B: r 服务器时,会将这些数据以cookie消息头的形式+ Z* d! Z* J, M# d4 L/ |
发送给服务器。通过这种方式,可以管理用户的% K, k6 z% \$ k8 n
状态。4 j- w7 L! ~% V5 [9 J+ w4 ^6 G
b,怎样创建cookie?; j: d( \+ j" s' s
Cookie cookie = new Cookie(String name,5 _7 Z5 G5 ?/ f
String value);
$ n0 P# O8 L4 m% t response.addCookie(cookie);
& y3 k+ ^: a+ K' Z5 f c,查询cookie
8 h3 M+ q, f! I //如果没有cookie,则返回null。5 w4 j: ?9 `- Z" _ r! `! e
Cookie[] cookies = request.getCookies();
6 J) k6 X! }1 o+ c" @& p, ` String name = cookie.getName();+ C- K& e! j/ o, k
String value = cookie.getValue();
2 F- ^) L" ?: u# n d,cookie保存时的编码问题2 d" i9 k3 P0 x: J1 e6 n% t
cookie的值只能是ascii字符,如果是中文,
, A( k4 S3 ^: X: I) |$ _ 需要将中文转换成ascii字符形式。- j# \4 C' `) T6 D5 X
可以使用URLEncoder.encode()方法和
, Q& P% x2 L# A2 f( U0 ?/ J& A URLDecoder.decode()方法来进行这种转换。6 ^* V3 u' `, l; |! W1 F' f1 t
e,cookie的保存时间: n! }; k8 k1 u1 o
cookie.setMaxAge(int seconds);
$ s' Y9 k0 k% A% L( ^5 Y6 c seconds > 0:浏览器会将cookie以文件的方式
: Z& I! k7 H" s# ? 保存在硬盘上。在超过指定的时间以后,会删除
5 L9 T5 U y' P/ r9 k( P! i j1 Y 该文件。
! M3 `5 X' m {; n seconds < 0:默认值,浏览器会将cookie保存6 B- c4 R& g& y$ b8 ?4 Z
在内存里面。只有当浏览器关闭之后,才会删除。
% N' R/ k3 y5 u \ seconds = 0:删除。
( F2 z3 U; X F5 t. G; h% w$ W f,删除cookie
- P( I# \/ h# r. @' P/ Z5 F 比如要删除一个name为"username"的cookie。+ s: D& j) C( n
Cookie c = new Cookie("username","");
5 F4 g9 B- r* `& ]. k: z c.setMaxAge(0);( H( |( ?$ ?+ b, E( E) }" y
response.addCookie(c);/ A! G3 V2 Q7 {0 `4 I+ }
g,cookie的路径问题
+ @" k- T6 {4 T9 T6 s3 S% h7 f7 s/ L 浏览器在向服务器上的某个地址发送请求时,
' u- {! G; I/ w& Z 会先比较cookie的路径与向访问的路径(地址)是' j* @, b% V9 J( M, @( X+ @( w
否匹配。只有匹配的cookie,才会发送。) {4 y( ~4 u7 b$ K( a/ ], L: q
cookie的路径可以通过
! x3 ?6 E2 ~, b% T cookie.setPath(String path)方法来设置。
* e" R6 l, W n. r6 C 如果没有设置,则有一个缺省的路径,缺省的1 G* b, c& e, i, W3 i4 _/ @+ b6 l! J
路径是生成该cookie的组件的路径。
3 d: [ D# K5 n* E* P! Z* S8 A 比如: /appname/addCookie保存了一个cookie,4 @& P3 e( i" B; \+ n
则该cookie的路径就是/appname/addCookie。
! ]' O; A0 S' `) M0 f8 L
4 o& c& S" G! S. L 规则:
% {- d. E+ X; \# { cookie的路径必须是要访问的路径的上层目录
; A: x# @0 A) z8 a9 J 或者是与要访问的路径相等,浏览器才会, ]" j# E' S* h/ G
将cookie发送给服务器。& X3 m3 I1 m8 o4 S
7 r% m9 X: ~9 k- A1 N0 G" `- d. U
一般可以设置setPath("/appname"),表示访问
, o) S9 S# z; G% [3 G/ x# D8 V 该应用下的所有地址,均会发送cookie。* h2 c+ m% X2 V" V1 m( I3 V) L
h,cookie的限制
; m4 s: m# }! K: c# |; b6 b) P; S0 n cookie可以禁止
4 t& I/ a2 S0 [5 G/ M7 U8 l( o cookie的大小有限制(4k左右)" w. O+ }+ O9 B" Y! }; J
cookie的数量也有限制(浏览器大约能保存300个)
) k6 R4 G& V: i8 F/ U9 V cookie的值只能是字符串,要考虑编码问题。! f) O3 Z) G6 ]: @8 H( e
cookie不安全5 A, ^$ K* X2 K. |& P$ U
练习:
2 {+ I* _0 x2 D 写一个Add_FindCookieServlet,该servlet先查询9 b' h- z6 u9 ]2 ]9 x
有没有一个名叫name的cookie,如果有,则显示4 _. _; N1 t0 j6 @! l1 m- m
该cookie的值,如果没有,则创建该cookie( Z2 `, l$ Z5 b( T
cookie的名字:name,cookie的值:zs)。& M! q% J0 g: t j1 u! i8 m
, @" h) ^ L9 C9 n
; h3 Y& ]: j" t7 g' h) E) X 4)session ( e' V3 R- l4 F$ \+ j
a,什么是session?
) X) e0 E- l C* y/ V5 D j; ^ 浏览器访问服务器时,服务器会创建一个session; u# S4 Z4 }0 M" G8 F4 f
对象(该对象有一个唯一的id, 一般称为sessionId)
, d; e- y+ L4 g 。服务器在缺省情况下,会将sessionId以cookie9 ~6 ^' S/ i9 X q
机制发送给浏览器。当浏览器再次访问服务器时,
. w3 X* x' s/ W1 y" Q6 p5 R$ z/ g 会将sessionId发送给服务器。服务器依据sessionId( ]% K: P: H7 T1 `) d; n
就可以找到对应的session对象。通过这种方式,
" @3 i' l# Q) R4 I' z5 W 就可以管理用户的状态。( l6 o9 w4 c* \; {( c
b,如何获得session对象) p- C6 e8 V' G
方式一:6 N) Y& ?8 M3 {$ x. _
HttpSession session = i, f" P2 N+ Q; V
request.getSession(boolean flag);
) V1 }- f- K. E2 x7 D0 m# R/ A 当flag = true:
& C3 C$ Q/ X. l: ~ 服务器会先查看请求中是否包含sessionId,
; J v# n- U& Q2 s$ R9 t 如果没有,则创建一个session对象。/ B+ U% M8 E* N3 Q9 s* L% Z& F
如果有,则依据sessionId去查找对应的
% g2 B2 a$ T% y j session对象,如果找到,则返回。: \- ^3 P7 ~! E* b, L. |, w
如果找不到,则创建一个新的session对象。! r+ }8 x, `7 p
当flag = false:
+ v1 g6 W! c& j& r/ k& M! O6 j' y 服务器会先查看请求中是否包含sessionId,
& [+ F# t ~3 p" K* U. m 如果没有,返回null。0 F3 b& f, K+ y5 G
如果有,则依据sessionId去查找对应的# p) z5 M4 {" L, `: H! o
session对象,如果找到,则返回。* S9 W, A) v1 [5 ~: k2 _
如果找不到,返回null。
9 @! V' H: A1 k8 b8 f 方式二:3 ]' d* |' K5 c& k: }- N7 Z* s! Y
HttpSession session =
6 K' m( r% e# @4 t, B/ B: s8 p( W request.getSession();
& n) b8 D. ` p9 v( u 与request.getSession(true)等价。
7 T/ D& |" Z# Y( {& Y c,HttpSession接口提供的一些方法
( N( F2 f3 a3 b' I //获得sessionId。5 m! {' E' E" w: u6 x) {
String session.getId();
! i( t" i) r# Y //绑订数据5 I3 p7 B. U& c; b# G
session.setAttribute(9 p7 x8 Y5 O7 @9 u$ C; n1 L: J( L
String name,Object obj);6 U+ a [/ j. s$ ~3 H8 J. W
//obj最好实现Serializable接口(服务器% J) V. j8 ~$ b) Q4 G
在对session进行持久化操作时,比如钝化
! G; `1 T' \+ k/ [4 [% A 、激活,会使用序列化协议)。
: \8 ? q+ P6 m Object session.getAttribute(String name);* Q% X3 m* d$ |1 z
//如果name对应的值不存在,返回null。
c" ]/ n6 Z- B: ~8 B) L session.removeAttribute(String name);- `: g$ ^0 i8 M& Z+ D
d,session超时) t4 g; {2 v" E, R
服务器会将超过指定时间的session对象
/ ?! ^2 Y- D1 j- a 删除(在指定的时间内,该session对象没有9 |% U; p; u# a) v3 ?2 o8 l' Z
使用)。$ u2 j+ w3 A* W
方式一:
" c1 q7 R- b% y6 b# n session.setMaxInactiveInterval(
) f; C; l! t9 Q$ B, s- ] int seconds);
* ~; s# _3 e9 |. {1 I 方式二:
1 E* m# m0 J8 Z+ I; e1 ^ 服务器有一个缺省的超时限制,可以2 h7 l* w- O8 b1 O0 Y
通过相应的配置文件来重新设置。
9 T. t% Q r: y3 C& j+ @4 V8 O 比如可以修改tomcat的web.xml(
1 {# {, `5 t/ x/ [/ |2 A/ a tomcat_home/conf下面)。
) ]* a, E& [3 b% l- K3 Q <session-config>$ F$ t4 h: y+ ]+ I
<session-timeout>30</session-timeout>
( g! ?" H' L. I: T. X) k. A </session-config>5 z0 B5 F# ~4 H: y) N+ q
另外,也可以只修改某个应用的web.xml。( L: g6 h a) L) {) J2 V
e,删除session
6 L8 _, B' ~( X8 H# c$ S session.invalidate();1 z2 V& p" C' c: c/ B0 t" ]& J6 Q
8 o1 A/ r5 w4 P$ H3 h+ v
案例:$ ~! A5 X- k5 C
session验证1 ~& K% {9 i1 _7 [6 Q% p
step1 在登录成功之后,在session上绑订一些数据。
) N( Y4 A. H2 {3 L 比如:1 V7 p" y6 f3 c6 A' d+ M( x0 W
session.setAttribute("user",user);" x7 [8 s& k9 O# N7 E+ j
step2 在访问需要保护的页面或者资源时,执行8 g$ `0 O9 v# G2 T, ^! t1 L$ {6 @7 J
Object obj = session.getAttribute("user"); X) f& s- [3 f5 _8 _( n
如果obj为null,说明没有登录,一般重定向到1 a" ?: e4 ]. L! I" y
登录页面。% r2 h1 y3 u: A1 Y) x" c
3 P# M; U; n) g |
|