该用户从未签到
|
状态管理: Z0 G1 ~, e& e0 v$ |9 |" r0 ~4 Z
1)什么是状态管理
' o% c) z' t' N" T 将客户端(一般是浏览器)与服务器之间的多次
1 ]8 Y& P' E( B: w2 f1 ^; x 交互当作一个整体来看待,即将多次操作所涉及的2 b. [4 K1 {1 R* ^
数据记录下来。
$ c# B( H3 u: Q Q' B5 b" Z 2)怎样进行状态管理; W; B: O9 Q8 O) e$ S4 o
第一种方式,在客户端管理用户的状态 J0 @+ L4 ~( c# d8 u* j$ c
(cookie)。& B1 F1 n$ E0 p; z6 Y I G
第二种方式,在服务器端管理用户的状态 m; y n9 D) }% g
(session)。! h3 T( W. G! H$ c) w( `
3)cookie
0 q3 E" y# Z! |2 k; \ a,什么是cookie? h* ]" Q4 Q! I% r7 \2 x$ O! t+ n$ P
浏览器在访问服务器时,服务器将一些数据
' `1 L' j/ O0 X: e; ^5 ]3 D' V 以set-cookie消息头的形式发送给浏览器。浏览) O" I) h( B9 [9 z( U, _
器会将这些数据保存起来。当浏览器再次访问
6 y8 i; J x7 W" i3 M 服务器时,会将这些数据以cookie消息头的形式
5 P6 @3 @% s/ D4 ~- Y, d I 发送给服务器。通过这种方式,可以管理用户的* P3 a+ t4 ^5 h, a: n! K
状态。; S, m" P) u" J6 C6 [0 H
b,怎样创建cookie?
# C6 t% U# v: ?4 Q Cookie cookie = new Cookie(String name,
: s% N, b) J, X" ?6 r# n String value);# _2 ^2 n! J3 M3 r, ?' O
response.addCookie(cookie);) I5 `! d1 }4 [, d! Q) x
c,查询cookie
6 |" O) c6 P! D8 ~& ~+ ?2 n3 x //如果没有cookie,则返回null。: r9 O* D* Q% O) {2 k. i
Cookie[] cookies = request.getCookies();9 }& Q( T/ }: h m. x+ U5 z
String name = cookie.getName();" ~0 M* j- O4 o5 [
String value = cookie.getValue();
3 J4 E" u: E$ h. t" A' H) e d,cookie保存时的编码问题 ~# O/ [- o+ k+ f
cookie的值只能是ascii字符,如果是中文,
; J' \8 b( P# M4 ^; A9 \ 需要将中文转换成ascii字符形式。
3 i/ A# ?1 |$ i j) ]+ y( M 可以使用URLEncoder.encode()方法和& I0 l7 w/ u; F, X# s0 V
URLDecoder.decode()方法来进行这种转换。
9 x5 I9 t0 l1 q) j+ ]% y e,cookie的保存时间- p9 ^& Z! I E% F. y4 {+ b7 E
cookie.setMaxAge(int seconds);
4 A; ^* j8 r$ a' D" g seconds > 0:浏览器会将cookie以文件的方式, y* C2 B3 @5 C( o0 L9 o6 ^
保存在硬盘上。在超过指定的时间以后,会删除
1 I" a" v$ |3 A( d 该文件。
: K2 ?7 w% K1 u% I4 C' o seconds < 0:默认值,浏览器会将cookie保存5 u" g" K2 w o1 U6 o" T
在内存里面。只有当浏览器关闭之后,才会删除。4 q ~4 E; E4 `8 m5 f
seconds = 0:删除。! E; z( u5 @: Y* Y
f,删除cookie$ }3 \$ e1 K' v2 ~; p
比如要删除一个name为"username"的cookie。
- c% `0 A) C1 g2 `2 E Cookie c = new Cookie("username","");
3 |1 M. V5 [% n1 l; o. T S1 F c.setMaxAge(0);
+ @% o: b K6 [; v response.addCookie(c);* B9 h; P4 O2 V7 X+ P+ a- F1 V, {/ o
g,cookie的路径问题. L& N8 y1 Q5 V8 Q; M8 a# ?
浏览器在向服务器上的某个地址发送请求时,! C* M9 P4 `- m
会先比较cookie的路径与向访问的路径(地址)是/ N2 S7 U _; v) D
否匹配。只有匹配的cookie,才会发送。
, j# ] V# b9 X, f Q! J cookie的路径可以通过/ C7 `2 r6 u1 S: }+ s
cookie.setPath(String path)方法来设置。, M$ T1 R- h6 b+ t3 y4 C( t
如果没有设置,则有一个缺省的路径,缺省的
6 j% R9 N l) v7 | 路径是生成该cookie的组件的路径。
1 q9 W& \2 @# U t 比如: /appname/addCookie保存了一个cookie,* N* j& Z9 I- c- J. ~' @5 f
则该cookie的路径就是/appname/addCookie。, a, @% U, C+ d* ~* t" e
4 n) o1 |: r) a: ] 规则:( W7 _5 s# }: u4 @( u& m
cookie的路径必须是要访问的路径的上层目录
! R) v& Q% {. ^2 d: K8 D 或者是与要访问的路径相等,浏览器才会0 V) u9 k5 a: w. h2 C& s
将cookie发送给服务器。
y A3 N" x) ?2 n( M+ m# w ' v8 c( n/ b) ]# V
一般可以设置setPath("/appname"),表示访问
$ X+ {6 H7 }' T& I/ d 该应用下的所有地址,均会发送cookie。( x- F3 o3 k: j$ L! c
h,cookie的限制6 F5 {2 J5 @$ g$ m
cookie可以禁止
9 f7 X3 T7 O0 X7 S4 |9 K; m" } cookie的大小有限制(4k左右)$ ^5 r9 K. _( U- W
cookie的数量也有限制(浏览器大约能保存300个) / `' y& A# Y+ Q* v+ H
cookie的值只能是字符串,要考虑编码问题。
3 b4 D7 {8 m# g; Z cookie不安全7 j. B W$ j. D3 `
练习:) [# {1 @' V9 |2 g2 T/ W3 R
写一个Add_FindCookieServlet,该servlet先查询# B& X7 \: T5 d j$ V
有没有一个名叫name的cookie,如果有,则显示+ w, I8 F1 ^- Q
该cookie的值,如果没有,则创建该cookie(
0 L4 o( Z1 B! V1 z1 ]& Y cookie的名字:name,cookie的值:zs)。! s# G* r% A% y- f: T
8 P% ^* N+ w! ^( h) k% Z
0 j8 k5 x4 K% f' N 4)session # \& i0 s$ f6 }7 l, b0 j3 n
a,什么是session?- t# l! h8 Z z5 V! d
浏览器访问服务器时,服务器会创建一个session
/ [1 F: n4 i. m2 O0 n% Q2 c 对象(该对象有一个唯一的id, 一般称为sessionId)
$ V8 J/ {: }9 g. R2 ~* T 。服务器在缺省情况下,会将sessionId以cookie5 {% c0 N5 A" ?$ R
机制发送给浏览器。当浏览器再次访问服务器时,
1 g* ~" i& c1 r' X# c4 O: i 会将sessionId发送给服务器。服务器依据sessionId
5 Y# a( _4 |, J; E9 ?0 { 就可以找到对应的session对象。通过这种方式,7 X3 b* z" W# Z! ?; k [6 W1 G
就可以管理用户的状态。
) a! }1 {" m- I$ b6 p% ^ b,如何获得session对象% g% l1 Z; j. v8 I
方式一:0 V r3 x& u6 a7 x, P
HttpSession session =
! _# F3 D) e4 S( N1 \$ _; J' V request.getSession(boolean flag);8 m7 r8 E5 n8 c, Q7 F. Z
当flag = true:+ C" G- v1 [, p. h( r- v
服务器会先查看请求中是否包含sessionId,8 C# P3 f) N2 a- J; R
如果没有,则创建一个session对象。/ o6 V' l$ B& J9 H8 w
如果有,则依据sessionId去查找对应的
$ ?7 v9 b6 t: C! G# S2 n session对象,如果找到,则返回。/ `8 P; R. W2 s7 s0 O
如果找不到,则创建一个新的session对象。
* x7 J) X5 q. U+ \, m% v 当flag = false:
3 @ B% m! l, |! d+ g. A# h# ~7 { 服务器会先查看请求中是否包含sessionId,
% j, n9 C/ r5 t* [0 h- x8 K 如果没有,返回null。2 K) W8 Y c! e5 _! Z! |
如果有,则依据sessionId去查找对应的" T2 | C y N4 g
session对象,如果找到,则返回。
8 _$ [0 T" q* X( h( J) d; [) d 如果找不到,返回null。$ p4 p& m K# O
方式二:2 P ~* q& c$ l- J+ Q S u
HttpSession session =
; Q' I9 g. t. T; o request.getSession();* R* ]: U0 k# V7 h$ P! @
与request.getSession(true)等价。! j/ {* ]: q: {7 m1 P1 E/ T
c,HttpSession接口提供的一些方法
2 H. {: D% E/ U/ b/ W1 a8 b) ^ //获得sessionId。* W1 a8 }2 k0 }9 n0 N
String session.getId();+ G1 n Y3 ?) i# f( U1 l- v% t
//绑订数据
0 {' O, f; U/ ?7 S' ~ session.setAttribute(
+ Q6 M5 j6 z6 K/ }; p$ H String name,Object obj);
, c. W6 u& z1 f //obj最好实现Serializable接口(服务器) h1 \" P+ H4 q3 \' G$ R2 a
在对session进行持久化操作时,比如钝化* ~1 ]% I) w! j2 F
、激活,会使用序列化协议)。
; T. N5 S8 I4 g. w: r5 v- O Object session.getAttribute(String name);
8 O# P4 }9 E9 G {4 @" \ //如果name对应的值不存在,返回null。
7 F3 b" w1 y* t session.removeAttribute(String name);2 [/ |2 @; p x
d,session超时$ |6 A* p& |( s" a, e
服务器会将超过指定时间的session对象
0 C) Z% B4 ?5 O2 t$ I. u 删除(在指定的时间内,该session对象没有
4 ~" `; I9 y6 g% e6 R 使用)。" D' Y. _6 G. T4 h" Q9 [. u7 N
方式一:
9 E- t- J7 Q. E1 {3 A session.setMaxInactiveInterval(+ B+ Y" \/ f( D3 F( r* @4 J# {
int seconds);
& Q$ c" f$ I, G/ y& T4 u 方式二:
. {3 Z6 n W* B3 |/ d. b$ C 服务器有一个缺省的超时限制,可以# I |7 ~. a# b* b
通过相应的配置文件来重新设置。
7 |! ~+ Z# d; n" V k5 @& O7 h 比如可以修改tomcat的web.xml(
* o7 H. G2 [, ~0 f tomcat_home/conf下面)。' r* q2 G$ r5 z1 C5 W+ o# Z( ]
<session-config>9 F5 z% E4 q* y- p$ o8 R* a
<session-timeout>30</session-timeout>1 F9 a( p+ o" C* n v
</session-config>' C1 C; x9 {, u3 p2 ]
另外,也可以只修改某个应用的web.xml。8 A8 R* @; g- W4 `* Z0 @: ?
e,删除session$ z6 k& k w8 Z5 g# Q0 g' P/ L- j: ~
session.invalidate();% L$ C3 b; W, Q! T
0 T1 s+ r6 P! h |3 T6 v
案例:" b! h3 A% }0 d. y
session验证8 h6 v! U4 o. N# z( \8 ?
step1 在登录成功之后,在session上绑订一些数据。
w- n+ G& s% ^+ H- T/ J 比如:" @0 L- \' F2 o
session.setAttribute("user",user);% e! I- m& f0 u0 H' K
step2 在访问需要保护的页面或者资源时,执行0 ?+ M: q. Q0 E! }! S1 ^
Object obj = session.getAttribute("user");; U. x' T; c8 \( Z9 X7 U
如果obj为null,说明没有登录,一般重定向到1 @8 L$ X1 K$ F y, p
登录页面。
" S. a6 I9 l5 v/ k/ j/ N
& n: P4 M: T% H1 b& L5 ] |
|