该用户从未签到
|
2、状态管理$ B. A8 s5 y( q. D& d3 k
1)什么是状态管理
( T M* p# C5 d 将客户端(一般是浏览器)与服务器之间的多次
! T( @7 _8 ^8 W% G* n 交互当作一个整体来看待,即将多次操作所涉及的
$ V1 h1 T6 U2 g8 K+ S n' @ 数据记录下来。
( w) H) G5 q) _* A8 Y* G 2)怎样进行状态管理
0 w- _$ C4 M( K2 K: q/ N# c 第一种方式,在客户端管理用户的状态4 ]8 t6 q4 l/ L; c% H+ W
(cookie)。 P0 u; ]& K- v( w* N1 I, @3 J
第二种方式,在服务器端管理用户的状态% N; {# ]& K( B) Q, p2 Y
(session)。
; w! z: X8 X% h/ g+ Q3 M3 J' d0 b. W 3)cookie/ S) n/ h, T ^- } `0 |
a,什么是cookie?* r6 s0 X5 @# Y
浏览器在访问服务器时,服务器将一些数据$ G5 k3 j: {* s% S, |- p& I' l
以set-cookie消息头的形式发送给浏览器。浏览
% F& {+ T; t1 d& F9 ^7 O, e 器会将这些数据保存起来。当浏览器再次访问) e7 F" s2 k8 x @; X) a6 M
服务器时,会将这些数据以cookie消息头的形式4 T; L0 r- m% K( @$ b# j6 c
发送给服务器。通过这种方式,可以管理用户的4 q5 a. Z! J9 x' w0 Z( Y
状态。: W9 L/ j) w8 ]5 G
b,怎样创建cookie?
0 L% U. ?5 e8 _: T Cookie cookie = new Cookie(String name,0 p2 g% a b% l; D3 N
String value);1 }( g9 v! L( i' C# K y5 @
response.addCookie(cookie);
3 t* ?4 s L# ^ c,查询cookie1 |# X, O9 D% L. T6 f
//如果没有cookie,则返回null。. R7 M1 Z8 G: L- p
Cookie[] cookies = request.getCookies();
# K) |6 R8 l7 q+ l4 L String name = cookie.getName();9 Y% r# K1 y* h7 [3 A) X* ^# f) K
String value = cookie.getValue();
! h' G! j7 e8 O d,cookie保存时的编码问题
1 m; M: A" U! g+ t! L# O- ? cookie的值只能是ascii字符,如果是中文,
e! ?5 Y K" e; I6 ~' }8 e. J0 s 需要将中文转换成ascii字符形式。
# f K3 Z& M/ X 可以使用URLEncoder.encode()方法和# l3 K s+ o- H- C; S
URLDecoder.decode()方法来进行这种转换。
% {- j2 A- ~. x% k6 N# S6 a# K3 C; v' x; K e,cookie的保存时间
" Z6 G/ l/ }- ^' c1 D1 b8 ~' M cookie.setMaxAge(int seconds);
9 Z) h \' x5 N3 L9 J G2 e seconds > 0:浏览器会将cookie以文件的方式3 a# Q' y$ J" Y2 G$ a& k/ r- S
保存在硬盘上。在超过指定的时间以后,会删除
" j; X* [) g/ H2 H 该文件。
3 j0 e3 |* L& e5 c6 X( ~. _ seconds < 0:默认值,浏览器会将cookie保存
- Q& F0 k; \% s 在内存里面。只有当浏览器关闭之后,才会删除。
7 V- |! `% S2 f) j( N seconds = 0:删除。
: q3 u9 i' ?0 ?2 }- z f,删除cookie
$ O7 j8 a6 u1 U# Z 比如要删除一个name为"username"的cookie。
! V1 p5 v* F& U) ^$ m4 ~$ Q. ? Cookie c = new Cookie("username","");
7 G# W: ^3 e* o0 r c.setMaxAge(0);
7 j7 @% O! S2 ?9 K$ f& F3 @1 _ response.addCookie(c);
3 _# l5 u7 n: Q6 _, J g,cookie的路径问题
6 d6 `0 N2 m# g+ \0 |1 J; R& r) b1 | 浏览器在向服务器上的某个地址发送请求时,
4 Q8 ` n3 r" ~5 H6 ~( Z 会先比较cookie的路径与向访问的路径(地址)是
* g7 M+ A* K0 S4 T1 ]& R7 @ 否匹配。只有匹配的cookie,才会发送。
1 x) T; c) \4 P4 V( e cookie的路径可以通过+ t$ [" s& v) ~+ L
cookie.setPath(String path)方法来设置。
8 L6 l+ J( e, @3 }7 S- h2 h 如果没有设置,则有一个缺省的路径,缺省的+ M7 s- o8 S! _& a+ J, t
路径是生成该cookie的组件的路径。2 M) b" ?2 b2 l$ @
比如: /appname/addCookie保存了一个cookie,8 T( B! v% |6 \) h: T3 y" J
则该cookie的路径就是/appname/addCookie。
1 T9 n" y5 v8 V' o$ g4 W + r: O+ F( q' |5 j- }
规则:! E, d1 B: V" G+ X7 _' C
cookie的路径必须是要访问的路径的上层目录( n: i `; L. t7 ~' T3 \: J# Z
或者是与要访问的路径相等,浏览器才会; d. t5 _' ? v& O# V
将cookie发送给服务器。3 e# q" G0 L4 C$ }+ @& ^
/ }4 |: `+ I+ c% Y$ B& F
一般可以设置setPath("/appname"),表示访问- H4 u+ N, n1 O8 S5 ]) R |! r- M
该应用下的所有地址,均会发送cookie。
/ B/ d# Q# _5 h9 Y. z' { h,cookie的限制
( C' @* d( G0 |1 v+ ? cookie可以禁止, F4 R: q3 S5 B* x3 U# A
cookie的大小有限制(4k左右)
' L/ g1 R# A6 S$ C; a g7 R) v cookie的数量也有限制(浏览器大约能保存300个)
) N6 `9 |6 l" m5 ? cookie的值只能是字符串,要考虑编码问题。+ y2 z# C Z7 `/ F$ Y* P* I. M. m$ _8 n
cookie不安全
. S( i3 h0 K) I2 t0 l- X" s 练习:2 S4 I& Z& h" B' r5 p* h3 |+ F
写一个Add_FindCookieServlet,该servlet先查询3 e/ L& @4 Q! D5 T) p
有没有一个名叫name的cookie,如果有,则显示
7 J( W, s7 G6 D7 s- I 该cookie的值,如果没有,则创建该cookie(
& Q1 }7 w1 B! C8 Y/ F2 P; _8 I cookie的名字:name,cookie的值:zs)。# o9 d1 c9 r- z
0 y& z D6 {: I: o* `; a
/ a& D6 M' |( |( m0 Y. M2 Z a* `0 Y
4)session
5 k1 @2 `7 v# r# M) D" R a,什么是session?7 Q: f0 }: U1 I! F* p! N
浏览器访问服务器时,服务器会创建一个session
' _8 ]! ^6 x% G& D M) Q 对象(该对象有一个唯一的id, 一般称为sessionId)
9 y& s0 T. v1 R, G. G$ j" T' h& Q 。服务器在缺省情况下,会将sessionId以cookie; S0 d6 }2 F, m- l
机制发送给浏览器。当浏览器再次访问服务器时," |0 }) u( |! \4 |% X
会将sessionId发送给服务器。服务器依据sessionId
/ _9 ~$ u* t# t9 d 就可以找到对应的session对象。通过这种方式,. T9 S" M' u6 |: a# v8 w+ T
就可以管理用户的状态。
7 g5 Q4 ?, q8 W b,如何获得session对象
3 |% o+ z4 u2 `' j4 I 方式一:% ?% X5 Y# S" d; q+ w- Q6 ]
HttpSession session =
' r8 ]2 l8 G4 {6 r4 U1 k: l request.getSession(boolean flag);
' H( V' ~3 {7 r3 M+ K9 F 当flag = true:
/ I! @. j& E! S+ S6 x 服务器会先查看请求中是否包含sessionId,
( E5 _4 L( }; J' I; D 如果没有,则创建一个session对象。! |. J2 `' h$ r- Z- e# _' a
如果有,则依据sessionId去查找对应的
) t/ P9 s5 V; k% L: [( X session对象,如果找到,则返回。8 O% z# ~& I% ^9 L/ C
如果找不到,则创建一个新的session对象。3 A8 |% Y4 a0 `7 M' r( t- p' m
当flag = false:
" a. ^. ]" d+ E* a9 t 服务器会先查看请求中是否包含sessionId,4 S. u4 C' _3 ?# w+ q
如果没有,返回null。- I7 q5 i) F' w2 @7 l0 y" u
如果有,则依据sessionId去查找对应的; H2 B$ g3 _* F; Z
session对象,如果找到,则返回。
; K. u" Y `4 ~2 U5 K: ?& x 如果找不到,返回null。
' b2 F6 L, m' s4 J 方式二:& I3 ~: G/ m! {" S, i
HttpSession session = ' w: t5 C9 D: _: s: e
request.getSession();
7 c H7 |2 E% q+ t& z 与request.getSession(true)等价。
0 Y) s3 X- ~% U0 V- g g c,HttpSession接口提供的一些方法
7 n! }+ N! |5 s8 B, }" \" z+ p //获得sessionId。( f* h' A5 O. d, a7 B& v$ O+ J: z% w8 ^
String session.getId();: j8 l [+ b0 s! K! h! `( k# o
//绑订数据3 S: c0 i% o: H3 v1 R# n
session.setAttribute(- H" J; o6 K5 h$ t. a% e+ ]
String name,Object obj);* p- f5 u8 A; t& K' O
//obj最好实现Serializable接口(服务器* d" J1 E- n8 ]6 s" d
在对session进行持久化操作时,比如钝化
( f0 b4 }1 {* G 、激活,会使用序列化协议)。
; V) T& x& W+ G W; s; t Object session.getAttribute(String name);
) k" O$ u1 i9 T; U% H //如果name对应的值不存在,返回null。$ D' f) ?6 H8 z" D; D
session.removeAttribute(String name);
8 O, \6 {2 Z o9 N" t2 R d,session超时
& d3 M3 E j5 [0 o8 g 服务器会将超过指定时间的session对象
3 q# F. }, L7 w! W. |* p! J/ y 删除(在指定的时间内,该session对象没有2 X# k% n; A+ c- ~. J$ P
使用)。 y, z) I8 ?0 q
方式一:
! m+ _' w! s. A7 ]. C+ M" f/ _- S8 x session.setMaxInactiveInterval(9 p7 I8 j/ q* }+ a0 i
int seconds);
, k2 ^! M9 D: p1 R+ d; A* T2 U 方式二:
1 L+ G+ t% C. q* |% H+ d) H% ] 服务器有一个缺省的超时限制,可以7 K; C: I d3 v* O+ K: W/ p( `
通过相应的配置文件来重新设置。
; s9 S g4 k- S1 U) u& ]/ P 比如可以修改tomcat的web.xml(
& }! l2 G) L& p/ K6 y) V3 y" K/ y3 S tomcat_home/conf下面)。
! Z5 w& D4 W! z. W0 {- j; z. q" l9 O8 E2 L <session-config>
$ g% r( N6 S ]& b2 C; Q; x7 k5 y <session-timeout>30</session-timeout>7 K$ [- q. u) V1 g/ D
</session-config>
* I! x( V; U- M: G4 I4 W 另外,也可以只修改某个应用的web.xml。
/ q X/ @8 o; z# {( v. B! O e,删除session
9 P2 E( |5 i, i9 S session.invalidate();
# s/ t3 b6 u4 _2 K3 l
( {5 {* x5 f, l; x6 U, ~ 案例:
1 w7 o) W( t/ S+ g session验证
7 ~/ @0 {8 `* n9 ], A& ]( I step1 在登录成功之后,在session上绑订一些数据。 @- w2 t: y, r$ x/ [& @
比如:
8 p- j. M! T9 B6 H5 h session.setAttribute("user",user);+ C7 q- j) ~8 z a2 i! C5 R* a2 a) E
step2 在访问需要保护的页面或者资源时,执行
3 e+ q9 P! z' B& t7 Z) T K4 i' W Object obj = session.getAttribute("user");
5 l) _4 f+ }' B8 G$ L3 a- v. D 如果obj为null,说明没有登录,一般重定向到
6 Q( R8 w7 T; [* F 登录页面。9 C+ Q9 Y1 W7 S, }# t; Y# j
|
-
总评分: 帮币 + 5
查看全部评分
|