该用户从未签到
|
状态管理
# m+ x( f) W' m2 N* M7 o" w 1)什么是状态管理
, G8 |7 H7 c, e; ?1 f: M7 C 将客户端(一般是浏览器)与服务器之间的多次( }' X, J6 _+ P r7 t
交互当作一个整体来看待,即将多次操作所涉及的7 v5 o# b/ W' c3 j% z& s
数据记录下来。2 ^' I0 w, W/ N9 h" n3 `$ X
2)怎样进行状态管理; |: t+ b. ^0 @" U; i$ ~6 o$ e4 V
第一种方式,在客户端管理用户的状态
& K2 ^+ w" H2 y4 u1 C (cookie)。7 R1 P- t1 z7 W7 y1 O& d7 Q
第二种方式,在服务器端管理用户的状态
) l! j0 i5 H3 v, A- `3 z' A (session)。3 o, H L4 h/ K
3)cookie( k5 S; D! Q9 N) f) R
a,什么是cookie?
* _8 L1 Q4 O7 R5 k 浏览器在访问服务器时,服务器将一些数据
" X3 x; U& k% ^# c' W 以set-cookie消息头的形式发送给浏览器。浏览# u: \- T4 M5 S+ t# U' m+ F
器会将这些数据保存起来。当浏览器再次访问
$ H7 `4 ]7 s5 y; C6 w; r4 L* g 服务器时,会将这些数据以cookie消息头的形式1 b" N! `; G+ T% ~7 h
发送给服务器。通过这种方式,可以管理用户的
( X" Q% \/ w) X; k 状态。3 I3 H- k9 ]# Z
b,怎样创建cookie?0 d$ r; |7 {5 W" Q
Cookie cookie = new Cookie(String name,
; J) P7 d; s# u+ I% s String value);
! Z$ @% y$ D$ q4 M response.addCookie(cookie);
1 ~0 z9 f) T+ r/ v3 w, e c,查询cookie2 E% P! N7 U4 J, s0 T) [1 C: ~
//如果没有cookie,则返回null。: S Q* I7 W3 y- Q! O6 v3 o
Cookie[] cookies = request.getCookies();
' x2 ~7 A% F3 r( B, \ String name = cookie.getName();; ]7 w- }2 v# H5 Z/ i# R0 L" `
String value = cookie.getValue();
$ Z# E& e ^" r; A d,cookie保存时的编码问题; w* u4 c( k( W( [
cookie的值只能是ascii字符,如果是中文,
3 s$ { c5 v w6 V 需要将中文转换成ascii字符形式。2 t7 w [& L) R& P$ r
可以使用URLEncoder.encode()方法和
1 W' j& s# ~/ }) s URLDecoder.decode()方法来进行这种转换。, ]# W1 e4 x+ v+ m7 t0 D6 m
e,cookie的保存时间; @* Z5 g5 D% |1 T* P+ G) F0 h
cookie.setMaxAge(int seconds);9 ]. x/ @1 a# S6 K% p9 l2 J. K
seconds > 0:浏览器会将cookie以文件的方式
/ q b, W4 z" o0 F/ ~3 q 保存在硬盘上。在超过指定的时间以后,会删除
5 m I: S: I% C7 A7 P" U 该文件。
' p. y8 }. ^3 ~! \5 ^ seconds < 0:默认值,浏览器会将cookie保存5 X% f/ B3 j1 R# S: U# ^( l9 T5 k* _, V
在内存里面。只有当浏览器关闭之后,才会删除。8 O H2 T, `* h7 |- ?, n
seconds = 0:删除。; Y2 X$ t6 B& @+ Y n
f,删除cookie% r* p/ |: f( w# v6 L; P/ H( N
比如要删除一个name为"username"的cookie。
' ^8 n+ N9 t+ U- ^4 F Cookie c = new Cookie("username","");: w+ Q( f, O1 D$ a1 m) P ^
c.setMaxAge(0);
+ H7 C/ J; a0 ~ response.addCookie(c);; }8 Y% b2 H. s, `9 d V
g,cookie的路径问题
l \7 k g4 i* ], [; [$ s) Z 浏览器在向服务器上的某个地址发送请求时,
( J! `* C7 ?* m 会先比较cookie的路径与向访问的路径(地址)是: ?, ~) U- q9 l( m0 ~8 Z7 D2 V
否匹配。只有匹配的cookie,才会发送。
1 X# k3 m, a" p7 I- @ cookie的路径可以通过
* H: l7 E3 g; `+ d' d cookie.setPath(String path)方法来设置。
& W7 @# y5 n- Z, k$ u 如果没有设置,则有一个缺省的路径,缺省的# N& E% F6 p2 V8 x: v
路径是生成该cookie的组件的路径。9 b; N4 E: X! u1 b/ G2 ?8 d
比如: /appname/addCookie保存了一个cookie,
$ F; P& O9 D6 j' j, R( N 则该cookie的路径就是/appname/addCookie。
; M4 A& |5 b# l) v ( X/ n- m3 a5 E& i# Y: |) p
规则:
& B8 ^7 g2 A4 r: y2 V cookie的路径必须是要访问的路径的上层目录) p/ ]0 `# Y @0 _7 c' J5 J- G
或者是与要访问的路径相等,浏览器才会
( I8 `( c$ i) ?1 b3 K K8 E5 n 将cookie发送给服务器。$ F9 D( b! W: N7 U4 g3 Q. K
C9 m" ?& X% q2 Q
一般可以设置setPath("/appname"),表示访问
' W9 y. \" k7 P 该应用下的所有地址,均会发送cookie。
+ ^% Q, ~2 t0 e2 k- G h,cookie的限制
" \& I. [' S( m! A% F cookie可以禁止- Z3 G6 w; ?# |- j) S
cookie的大小有限制(4k左右)' y! j) |% e+ w
cookie的数量也有限制(浏览器大约能保存300个)
( H: ]1 x8 \0 @7 b% S cookie的值只能是字符串,要考虑编码问题。# Q' h7 x6 C3 C% U$ r) e0 C- M9 S
cookie不安全
2 S# X0 b# k. U2 [ 练习:
- d" b- l0 q: u) U7 G2 o1 _ 写一个Add_FindCookieServlet,该servlet先查询
# X6 s& j+ ^' m- R. i0 b' u- N2 ` 有没有一个名叫name的cookie,如果有,则显示
+ O, P% m% y1 v1 N 该cookie的值,如果没有,则创建该cookie(" r0 }3 U/ t% D' n& A) f2 B
cookie的名字:name,cookie的值:zs)。
: ^6 i# }- V+ w% E . X( q: r J; w3 s$ ~
- ]# ~( N7 y" l7 E
4)session C; E4 E- O) B+ G6 [7 T
a,什么是session?" Q+ ]* }& K9 B$ K2 g7 F
浏览器访问服务器时,服务器会创建一个session0 X0 O; `/ k3 H4 k2 f
对象(该对象有一个唯一的id, 一般称为sessionId)
G# s4 p# R6 S2 ]! q7 p 。服务器在缺省情况下,会将sessionId以cookie! ~& y6 H- Z! ]5 i& @
机制发送给浏览器。当浏览器再次访问服务器时,
& Y' W7 W0 b8 G& _ 会将sessionId发送给服务器。服务器依据sessionId+ [0 X! W. i, g" E( D/ [# L) p2 t( t
就可以找到对应的session对象。通过这种方式,. f9 j1 J# ^* x ]$ J
就可以管理用户的状态。' W; n) S4 N7 [# d2 X6 k- e
b,如何获得session对象
3 t! n7 n" N+ S {, x 方式一:
# n) K7 L2 Z! A6 p) b3 W HttpSession session =
" R) N! Z5 O! p7 J: ?% O( c request.getSession(boolean flag);+ k2 P7 g8 l/ B( n
当flag = true:
" A1 @$ J1 k# R% k- }) a4 k 服务器会先查看请求中是否包含sessionId,( m; x1 L7 w' Z7 K/ E
如果没有,则创建一个session对象。
9 ?( S0 u8 Z7 _% R. X# n- W1 \ 如果有,则依据sessionId去查找对应的
! A# F6 H9 f& \" h4 X6 s session对象,如果找到,则返回。
! _' l U: U% I! g$ v9 D 如果找不到,则创建一个新的session对象。7 v p7 h" w' i3 b; a- v
当flag = false:
F8 u% f$ w, d% h% L5 u6 s 服务器会先查看请求中是否包含sessionId,7 V' q: i3 g, n1 D
如果没有,返回null。
8 f1 R5 ?4 t0 B& y 如果有,则依据sessionId去查找对应的
: O W: f) ^( v8 _0 v. q session对象,如果找到,则返回。
' x1 w5 a7 n% { 如果找不到,返回null。
O$ e X0 q9 K4 G, d0 B6 Y. i 方式二:1 f' G% V5 F, c% m" W4 U" H. s/ C3 j+ _
HttpSession session = * N% [- r: `. P
request.getSession();6 a5 }( B5 Y) j+ O0 F7 B4 ]. _* k
与request.getSession(true)等价。1 L) q+ D" F7 i6 o: J8 l, X9 V
c,HttpSession接口提供的一些方法. V- _/ g& L& x6 _- v- e* v1 n4 N. v
//获得sessionId。
V, y! P9 K# l* \" h& ? String session.getId();
5 B( H6 s" Z2 p4 E h) n //绑订数据 y* \+ z e+ b* [$ N ^ k
session.setAttribute(6 ]) |( j' m" z. h* Q8 K# L
String name,Object obj);! C F! q/ `/ |6 V% D; b
//obj最好实现Serializable接口(服务器/ y R: M* G3 P# t$ b( ?& L* ^
在对session进行持久化操作时,比如钝化
* M- n/ h+ i" @. C$ w# ~' I& d 、激活,会使用序列化协议)。
5 ^1 m* I2 Q! J1 i0 K Object session.getAttribute(String name);/ f" i' G! H: c* ]4 ?
//如果name对应的值不存在,返回null。
- g6 m! V9 {7 Z* v3 x3 Q, d X session.removeAttribute(String name);
* U7 G) }" \: z4 y) g0 s9 S. e d,session超时
" y# {( j7 ~/ C# V* O& z" V6 P 服务器会将超过指定时间的session对象7 ^: H1 N1 W$ ~+ d" }4 \
删除(在指定的时间内,该session对象没有
3 D t. A4 K- q6 G 使用)。
3 Y0 v" W# n3 ~' G# c: S: J 方式一:/ A" g, L$ c$ O8 X7 `
session.setMaxInactiveInterval(
" k+ P* X' h, r- x7 D3 y int seconds);
1 I1 T0 f& J" Y. q 方式二:* ^0 w5 @2 D$ k- K; h: t3 f; G
服务器有一个缺省的超时限制,可以
6 }+ x- `( z! u8 N 通过相应的配置文件来重新设置。
, [# d* M$ ?* a7 n/ _6 [ 比如可以修改tomcat的web.xml(
- v' O2 I- r% ]" L! M$ ]- w" c. l tomcat_home/conf下面)。3 | V9 O/ x/ N; w- C' q% ]# Q
<session-config>
7 C) k5 O* u: M3 I <session-timeout>30</session-timeout>1 O3 A% x. P. N- n9 t* Y( I1 k# n1 J
</session-config>
' B9 l) A$ ~( q# \/ D 另外,也可以只修改某个应用的web.xml。5 r, \0 s- a$ _
e,删除session
. y$ y) V l! z8 P8 [, ` session.invalidate();
" z- t! ]+ y9 j* z . l S m, R7 P1 {+ Y9 j
案例:
* N- h% r i/ U1 o7 V session验证9 Q- X4 r# z4 ]- F4 a! n/ V
step1 在登录成功之后,在session上绑订一些数据。4 K" M9 e. {; f9 N& e
比如:
1 q/ Z2 l& Z; I( q1 b session.setAttribute("user",user);3 e B* r" ~3 Z# B% w
step2 在访问需要保护的页面或者资源时,执行
5 A; z; R1 X$ R% U" S9 m) o; ?! b Object obj = session.getAttribute("user");6 @2 j; p9 \6 M5 h0 ^
如果obj为null,说明没有登录,一般重定向到
) M- f& G- A0 z) Q 登录页面。
, f. o7 X7 J, @, k' x: {. \1 s6 j, P- v+ ^
|
|