该用户从未签到
|
状态管理2 H$ ~+ r, x$ l4 `2 u
1)什么是状态管理4 T. e/ R& L" W4 z
将客户端(一般是浏览器)与服务器之间的多次. A8 M/ j0 e' T+ z
交互当作一个整体来看待,即将多次操作所涉及的" _; i! }! h1 }4 I
数据记录下来。
- S* O/ ~1 R0 j 2)怎样进行状态管理
( I% I4 L# ?. Z- d 第一种方式,在客户端管理用户的状态+ H5 C4 U# U+ ~8 q1 ~# s$ {
(cookie)。
1 M6 W7 N% Z, S5 K8 |$ S5 Q 第二种方式,在服务器端管理用户的状态/ Y; ^* x: f' Z% U' a" r% o
(session)。
) u; t j. N- M" `7 O& k0 G 3)cookie7 e( d" [' z% m' p9 ], P
a,什么是cookie?$ d' z0 R s5 Q) c9 U
浏览器在访问服务器时,服务器将一些数据/ v2 ~1 d! N2 r8 J- B% K4 k
以set-cookie消息头的形式发送给浏览器。浏览/ e& S1 _& X6 F% C, e
器会将这些数据保存起来。当浏览器再次访问
" u) q" E E8 @1 W9 q+ k 服务器时,会将这些数据以cookie消息头的形式0 Z3 Z- F; R3 E, v0 F$ j6 P
发送给服务器。通过这种方式,可以管理用户的
/ Z% F, X8 K4 }- N' l 状态。
' N4 W0 r7 o& M9 N* A7 _ b,怎样创建cookie?' O* K# M- P! a8 q9 L! X) g/ ?
Cookie cookie = new Cookie(String name,, ~6 A8 U* d9 H8 [6 X
String value);. m8 Q' T9 q( H. q; V& e, W) W
response.addCookie(cookie);) C3 u: \ l- R N4 r" X+ m8 G
c,查询cookie% Z& ~" ~( S1 z
//如果没有cookie,则返回null。, |' [# ~( G L' x
Cookie[] cookies = request.getCookies();
9 p* |3 Y* `* \: `' Y. Y String name = cookie.getName();- z) F* |6 g. Y" } _
String value = cookie.getValue();3 q, f8 s5 e. _! u; y
d,cookie保存时的编码问题$ {+ m7 U1 T2 x( p) u, w7 A
cookie的值只能是ascii字符,如果是中文,
: m5 _5 f: T3 [ 需要将中文转换成ascii字符形式。% r0 w' p9 ?; e$ s1 p8 }
可以使用URLEncoder.encode()方法和1 T+ o( k2 x" Q3 {5 L
URLDecoder.decode()方法来进行这种转换。
1 Y3 j) i: Y( e) Z/ S! {, g e,cookie的保存时间
- [* F# F. e* a# K, F( a% X+ ~" f cookie.setMaxAge(int seconds);- K, l0 h& h$ y
seconds > 0:浏览器会将cookie以文件的方式
0 o$ R y6 X9 d8 p 保存在硬盘上。在超过指定的时间以后,会删除, C1 o6 |) o+ \( R% Q
该文件。
; s! _2 n* Q1 G seconds < 0:默认值,浏览器会将cookie保存# i3 G, A3 W$ a
在内存里面。只有当浏览器关闭之后,才会删除。
0 b% T. |4 ~+ b/ k* p7 |. T: w t1 M seconds = 0:删除。
! o6 R9 e- l+ ~$ S: q" E1 |8 t f,删除cookie! B, O9 V" v) o2 z& w, }% Q$ W( u
比如要删除一个name为"username"的cookie。( u3 P$ F- q9 g1 s
Cookie c = new Cookie("username","");( G( ^! t; |. r, C; n7 a
c.setMaxAge(0);
& v R6 {- z3 ~( k8 B2 p response.addCookie(c);( Z+ Q& \ a: S9 W2 `# Y
g,cookie的路径问题
, V1 t9 o( X2 c( \. p* ] 浏览器在向服务器上的某个地址发送请求时,
( |: T. d4 i7 Z" I 会先比较cookie的路径与向访问的路径(地址)是% k i/ [: o% k* Y: W
否匹配。只有匹配的cookie,才会发送。
* R- f r0 H; b2 n- x$ r cookie的路径可以通过- R& Q# J- |- C( S5 u. w
cookie.setPath(String path)方法来设置。
( ]& k5 E4 q4 k8 q7 v. U 如果没有设置,则有一个缺省的路径,缺省的
# T. _, u% g5 j0 ~& u6 ~ 路径是生成该cookie的组件的路径。
9 L4 q' d, q! [ 比如: /appname/addCookie保存了一个cookie,
+ k% }" }) h8 n 则该cookie的路径就是/appname/addCookie。. s; {$ M& X' t& F, o% t6 J
7 p; @ w+ o3 G+ {# r+ D! u0 ~
规则:
$ n0 j/ p$ K: x5 b# K; G. ` cookie的路径必须是要访问的路径的上层目录2 ?2 j3 D+ ~+ u2 i1 v
或者是与要访问的路径相等,浏览器才会
" t8 t, R! b2 K- O1 t0 U 将cookie发送给服务器。% t) J6 |" X( C9 O* Z1 B
& X% ]6 t* v9 [: G
一般可以设置setPath("/appname"),表示访问' L. C) k: o4 q4 s5 m
该应用下的所有地址,均会发送cookie。& r# x' W& F" h, H0 h3 t
h,cookie的限制9 q/ |& w' \0 D0 ?* a1 z0 ?+ k
cookie可以禁止0 ^( w* F$ |% X6 s; a* M5 A
cookie的大小有限制(4k左右)- N% O( X3 m% D' E: \: i
cookie的数量也有限制(浏览器大约能保存300个)
$ n: _( a9 D) D4 ?5 u cookie的值只能是字符串,要考虑编码问题。
3 C K$ I" c" D$ C cookie不安全1 C( h. g( h% `
练习:
9 T0 h, @1 U4 D! l* C 写一个Add_FindCookieServlet,该servlet先查询' B$ K- `" Z$ F: ^5 H
有没有一个名叫name的cookie,如果有,则显示4 i: }+ j$ i% I4 V! V) f1 N
该cookie的值,如果没有,则创建该cookie(+ ?% n8 B# J+ [" Y* G" P
cookie的名字:name,cookie的值:zs)。
4 k( d* f& b: M, A/ R # c* o% g5 q1 w3 u$ ]2 s6 j
0 `, D& b9 J5 S8 L; d
4)session " N4 ]5 O3 Z0 L" ]# a' `
a,什么是session?
4 o$ {+ P. u0 E 浏览器访问服务器时,服务器会创建一个session) `# _* i a! @6 e5 k
对象(该对象有一个唯一的id, 一般称为sessionId)
% ]9 S- y( r4 v* e) k/ G+ S 。服务器在缺省情况下,会将sessionId以cookie
' Q j/ { @- m; t" A0 ` 机制发送给浏览器。当浏览器再次访问服务器时,
3 w# g+ P" I* ^. L 会将sessionId发送给服务器。服务器依据sessionId E: \: p/ n8 i* V" F
就可以找到对应的session对象。通过这种方式,
6 j; \% i' C! B 就可以管理用户的状态。. M Q7 ^0 r, o }% `
b,如何获得session对象% K) N! H. U! s8 I" a9 f. ]
方式一:
+ X% z) @; u. `% f* \6 z HttpSession session =
6 i3 y k- O- I9 p request.getSession(boolean flag);
1 P: T' [* O f2 n) [/ ?/ ?8 I 当flag = true:' K' a' r$ V1 R [" ]
服务器会先查看请求中是否包含sessionId,
8 s* L5 n5 }, K ?" c8 N 如果没有,则创建一个session对象。
- d$ E* k0 e4 y W; M 如果有,则依据sessionId去查找对应的1 r) W2 p2 |! k( e2 }
session对象,如果找到,则返回。# k3 @4 I0 @: z. I2 B
如果找不到,则创建一个新的session对象。) ]2 R% O' Y) b
当flag = false:/ G# a! j# w8 g$ ~4 b/ d; G( T
服务器会先查看请求中是否包含sessionId,5 E+ ]0 R: |5 o
如果没有,返回null。
" |+ L8 _2 y6 M u0 W" W) o) Q" W4 b 如果有,则依据sessionId去查找对应的; e; q3 _5 d3 |) I8 {. H7 g
session对象,如果找到,则返回。3 O6 o2 X# [3 k3 q W
如果找不到,返回null。0 F& e9 ~: n4 r3 A1 f) v7 P/ W, n
方式二:- P k$ l5 `) ] q& p0 u: ^" c( |9 H
HttpSession session = + f9 }% s& S7 ?8 C) L6 m
request.getSession();
& s5 N" _; i" N: ^6 y7 N3 m 与request.getSession(true)等价。( n2 w4 m8 h3 E; K% i) _
c,HttpSession接口提供的一些方法3 X9 x1 {, n) m; U0 R
//获得sessionId。
, c" C" V& Z+ z' C String session.getId();
+ p, u( J- T! G3 ?# A //绑订数据 \4 N5 w9 a8 A/ f3 I* w
session.setAttribute(
' I7 f2 z' [. }& v String name,Object obj);& y) l+ h+ l8 j9 m
//obj最好实现Serializable接口(服务器4 Y4 k M- ^( |9 z! C. z
在对session进行持久化操作时,比如钝化
5 T3 ]( F3 g3 y0 I 、激活,会使用序列化协议)。5 \1 y: o" ~& R8 \
Object session.getAttribute(String name);& n/ l5 C1 K8 M b; O1 ]( Y2 o
//如果name对应的值不存在,返回null。$ X3 [* s( W1 M; f3 q
session.removeAttribute(String name);
% x* G& K, m9 F/ `( T' A, Z d,session超时& U6 d% c6 e& O; j6 b5 b! {- D! R
服务器会将超过指定时间的session对象
- \7 I; h7 u% K) w( H 删除(在指定的时间内,该session对象没有
& I V' r; R% V; i, n) k9 N 使用)。
: s+ c' E1 c) k% |# ^8 } 方式一:
t; E- ^4 S& ~, g& w0 L! o0 y. p8 d4 w session.setMaxInactiveInterval(
3 J8 D% x+ l7 O int seconds);
. D R1 Q1 e9 B# t+ y- z/ g 方式二:" s/ E: _! W' |* @# _5 t. U
服务器有一个缺省的超时限制,可以
; Y& o" U( \# a9 z 通过相应的配置文件来重新设置。
8 l) b6 M b3 e! @; _# R 比如可以修改tomcat的web.xml(. K/ d1 \0 E! D1 A
tomcat_home/conf下面)。
# O0 M8 U# m4 f* D4 O <session-config>
% y& f% f) T& H3 q <session-timeout>30</session-timeout>& g8 u) M! c4 s }
</session-config>
' p/ o# R7 f% t' M2 {! c 另外,也可以只修改某个应用的web.xml。
- ]# \! d% {. U: S* T6 [" e- @ e,删除session4 Q8 Q$ Q& T- S% G
session.invalidate();( Z2 c" v& h. K! }9 ]3 a6 ?
; q C* d% E$ N6 G7 C* P 案例:6 `( D/ `9 Y2 l% L( j6 [4 Y* V
session验证- O& \+ B+ I; C4 R( X9 G
step1 在登录成功之后,在session上绑订一些数据。* w) z8 v* m/ J8 `) B
比如:6 `6 e. p: y9 N& Q' n. y# p
session.setAttribute("user",user);+ F, O' v* r, U0 c5 {
step2 在访问需要保护的页面或者资源时,执行
- B& m% I+ n& f Object obj = session.getAttribute("user");5 j& W$ O) r5 I; ?6 X% D4 r
如果obj为null,说明没有登录,一般重定向到$ q& I7 \3 T9 q6 H
登录页面。
$ v( D( ~( J; p6 K0 Y z/ n
4 @2 s" c0 f$ b) d& f |
|