该用户从未签到
|
状态管理
! K6 [" N8 n8 J0 M 1)什么是状态管理 V$ g; V* G& I" C( q1 L
将客户端(一般是浏览器)与服务器之间的多次0 {5 C5 C. [6 p
交互当作一个整体来看待,即将多次操作所涉及的
/ j5 Z2 t7 {/ i' {. r+ Q+ f 数据记录下来。' v1 r8 z$ d$ ]' W1 R9 u
2)怎样进行状态管理
l6 z; e6 c3 \. x 第一种方式,在客户端管理用户的状态
% V8 i- E) H0 F. T. ~% ^/ l/ X (cookie)。8 }; |( T+ w3 c: y- A/ U
第二种方式,在服务器端管理用户的状态
# g' \ L; J! e: p& D! Y! a (session)。
2 c( o5 i( E$ D 3)cookie3 l/ d4 |, L! X8 I
a,什么是cookie?) `: H+ _" | z6 M/ m7 [, ~# T' d3 {
浏览器在访问服务器时,服务器将一些数据7 P/ x; z9 x! ]- I( B+ N: {
以set-cookie消息头的形式发送给浏览器。浏览4 U7 m# x( y+ P* S( b: b5 o
器会将这些数据保存起来。当浏览器再次访问
7 N2 d+ f" d9 q: o8 r9 e4 ^; Y 服务器时,会将这些数据以cookie消息头的形式
, J5 \& D6 @: a- b) G 发送给服务器。通过这种方式,可以管理用户的
2 \$ T. e# U$ e" J* m5 @% `& s( ~ 状态。- h: ?5 l# i0 a: u( C6 P, t
b,怎样创建cookie?. d. R; n- u& Z" C5 Y
Cookie cookie = new Cookie(String name,
: P5 D, o$ _' V3 F$ x. s. R String value);# U0 k' P4 G% N, {8 U7 C! o! P
response.addCookie(cookie);/ A1 m4 H1 p/ ^# }4 {( F
c,查询cookie' H# l7 q( A3 n$ r" q
//如果没有cookie,则返回null。: f! c7 g. p* ]" R$ {
Cookie[] cookies = request.getCookies();1 U. N8 j$ s4 f
String name = cookie.getName();
) l" [/ ]/ ~/ n/ f3 q q8 V String value = cookie.getValue();8 `$ B. g- ~ D, q% F* T
d,cookie保存时的编码问题
, w, r; w4 P# ~' d cookie的值只能是ascii字符,如果是中文,
& |# b6 s0 K' P) L2 k- A% `$ J 需要将中文转换成ascii字符形式。5 b+ ?' u/ {0 x# y$ d
可以使用URLEncoder.encode()方法和
# l8 @. l; H+ k, I1 T) x2 } URLDecoder.decode()方法来进行这种转换。
D" Y) r' d- a+ d% q e,cookie的保存时间
( Z7 K+ E9 x$ ^! t+ e cookie.setMaxAge(int seconds);
# W( `' w$ p: }5 s. [ seconds > 0:浏览器会将cookie以文件的方式* j _" O, y+ B6 y$ K, k
保存在硬盘上。在超过指定的时间以后,会删除
9 n' `0 L, S1 d% I# N6 W2 N 该文件。
; C% `0 t' K0 u; |; Z seconds < 0:默认值,浏览器会将cookie保存1 B. F! |/ R; n9 w& r/ V( o! h2 o
在内存里面。只有当浏览器关闭之后,才会删除。9 E1 Z( `' v( l a/ K/ E# U
seconds = 0:删除。
. v) _) g1 @ L) E7 g f,删除cookie
% B/ P4 r" L7 i8 F9 T& [# {" Z/ B 比如要删除一个name为"username"的cookie。
+ h% J( Z& m9 O5 r Cookie c = new Cookie("username","");
: ?5 H8 L: T1 q |. H! v) a c.setMaxAge(0);
! Q2 k W2 L* n! E1 R% l response.addCookie(c);, `9 h) L4 x- |$ }5 [' a
g,cookie的路径问题
% K& L8 C7 F4 K2 S3 V 浏览器在向服务器上的某个地址发送请求时,
6 T# }) j; ~; y! r' C( ` 会先比较cookie的路径与向访问的路径(地址)是3 ^7 |( x8 G* f1 |/ M V" F, b
否匹配。只有匹配的cookie,才会发送。: y6 n$ ?& O- \# l2 x+ d
cookie的路径可以通过/ D, ], U1 q1 ?0 J5 ]
cookie.setPath(String path)方法来设置。
8 V0 @, I$ H; k 如果没有设置,则有一个缺省的路径,缺省的
" q9 S- L# t( x/ H- i+ j3 M+ N+ r/ L 路径是生成该cookie的组件的路径。
2 E5 K, d8 B: P( z5 @; G) L 比如: /appname/addCookie保存了一个cookie, V% _: X1 U- _8 Q
则该cookie的路径就是/appname/addCookie。
5 ^/ s& E& ?8 t1 h- \# X
! G5 G+ T" _+ l2 Z i 规则:. z" E; S& I# R9 p: l. f
cookie的路径必须是要访问的路径的上层目录
8 X. E5 @" {% Q( x% I% m7 C0 h( G 或者是与要访问的路径相等,浏览器才会/ h# z$ X# z X6 V
将cookie发送给服务器。
/ A7 r* N2 c0 G" v# n9 I0 @7 ` 1 z1 c. ^/ c# ]
一般可以设置setPath("/appname"),表示访问
+ Q- R- c) x5 G' `; c: Y' [ 该应用下的所有地址,均会发送cookie。' `4 z, i3 C1 M$ E( L q, }
h,cookie的限制
+ J! \! _0 o, F5 K2 l cookie可以禁止; B2 ]/ g: B4 |, a* y0 U
cookie的大小有限制(4k左右)
' ^5 d: E5 F0 c6 y cookie的数量也有限制(浏览器大约能保存300个)
$ V* t5 f& {- |/ b# C% R' b3 ]' H cookie的值只能是字符串,要考虑编码问题。
$ w" D4 c% _% X3 ~- A cookie不安全: N# W1 z. V+ v6 Z
练习:' j5 S2 l' r+ o6 u' w7 n" W7 m
写一个Add_FindCookieServlet,该servlet先查询
0 b( k) F6 I7 g2 h; ~$ Z9 T 有没有一个名叫name的cookie,如果有,则显示
& j. ]0 ] e! |# v 该cookie的值,如果没有,则创建该cookie(7 i, Q7 F5 m# Y
cookie的名字:name,cookie的值:zs)。* r: S" M, R% ^0 I5 t
/ }* ]6 z' ]4 ]3 s: T " j6 _5 W k3 W- c1 J$ L
4)session * ?' ~5 G0 U z( C
a,什么是session? a0 h* A I" f j- V, p% y
浏览器访问服务器时,服务器会创建一个session
% v5 f- }& X/ E# |, I9 j5 J 对象(该对象有一个唯一的id, 一般称为sessionId)
# r4 h: `2 F4 G- c: M) \+ L2 _ 。服务器在缺省情况下,会将sessionId以cookie
; g& l4 E {$ i& _& T P 机制发送给浏览器。当浏览器再次访问服务器时,2 v& q- W2 k7 u0 y+ z6 [
会将sessionId发送给服务器。服务器依据sessionId; c4 [# \1 `' k* \0 W. A- y3 a: t
就可以找到对应的session对象。通过这种方式,- ?+ s6 I7 K& l; b: |
就可以管理用户的状态。
& Z& v9 E. U$ {# \/ m b,如何获得session对象* G2 s0 [0 J5 N- @
方式一:
0 S; k: v- x: ^; ^ ?' X HttpSession session =
, U/ [6 v8 D' Q% ~% K) k request.getSession(boolean flag);
% T H0 m- l' [' R; j0 u1 ` 当flag = true:
7 g. l& J; ]$ ^ 服务器会先查看请求中是否包含sessionId,7 f* K6 D0 o/ P: }
如果没有,则创建一个session对象。
{/ H; L% n, e* A6 n 如果有,则依据sessionId去查找对应的
2 u: a7 t8 G q5 A. q* ] session对象,如果找到,则返回。
5 i6 j( W, {, ~% \% g 如果找不到,则创建一个新的session对象。5 x, w$ o' x3 R/ @6 _5 V1 C3 J0 j
当flag = false:
( S% B- y1 g- g4 @0 _: T 服务器会先查看请求中是否包含sessionId,$ M6 ? {5 n, Q% H% V" |1 y
如果没有,返回null。6 s" K8 f- e! C
如果有,则依据sessionId去查找对应的
T. z8 | \' T4 K session对象,如果找到,则返回。( A- J X, z$ e% o
如果找不到,返回null。
% b: Y) k; e/ _* _7 n# o+ @1 y 方式二:
5 }$ r/ T! K2 n* N6 l! L HttpSession session =
& H. I. d4 T& o: o2 v request.getSession(); [) J4 j! j8 t4 k
与request.getSession(true)等价。
- x3 o9 Y6 e0 S$ v5 i+ { c,HttpSession接口提供的一些方法
* O7 [3 X' [& { //获得sessionId。9 @1 q4 p9 F B1 j
String session.getId();9 K0 d) ]- D/ E
//绑订数据; O; B6 ]5 _. P8 b5 H
session.setAttribute(
/ G# J# h8 ~2 d6 J' Q& @# g; a( N String name,Object obj);- V0 |! d0 n: |8 ]3 W; k
//obj最好实现Serializable接口(服务器% u3 c7 t2 Q" q) V) s1 s% h
在对session进行持久化操作时,比如钝化& g' |$ P3 S/ j* i/ e1 d. L/ W
、激活,会使用序列化协议)。
: F5 B- O( Z. @5 ~7 H: { Object session.getAttribute(String name);7 ?& K# p% i8 e1 W
//如果name对应的值不存在,返回null。
+ I2 `) M, \ l session.removeAttribute(String name);* \1 T1 F: p+ }: G
d,session超时: s' U7 d: |6 U
服务器会将超过指定时间的session对象
" x3 P& R; k/ E! u 删除(在指定的时间内,该session对象没有
/ U* i5 {; }4 n5 v4 n) ^7 s 使用)。3 _0 k5 B3 H; ~
方式一:, B" V% O7 ]" B5 B, f
session.setMaxInactiveInterval(
' d8 h9 P6 w/ g7 ^' G; X: x9 m int seconds);. n1 A5 A& o/ z; s: K. U
方式二:+ n* X k+ c5 Y6 |( h1 D
服务器有一个缺省的超时限制,可以
' V" K. ~: V' L+ h$ C; H) ]6 A9 A2 i+ R 通过相应的配置文件来重新设置。
) B0 o& V( I% x- q8 G 比如可以修改tomcat的web.xml(5 Q1 C8 X5 V$ T) h
tomcat_home/conf下面)。
" x& T7 N" w, s1 r6 _* k <session-config>, A( x* H8 X! `
<session-timeout>30</session-timeout>0 B! W4 K( w0 O
</session-config>
8 L, X+ h5 M6 C8 c6 Y0 K/ E( i7 U 另外,也可以只修改某个应用的web.xml。8 I+ T: `( B/ K ?/ a) D) N
e,删除session
5 u2 u, d/ M: f. O0 m session.invalidate();
& a/ a. J1 p6 V, E) ~% H* Y1 Q3 f 3 G/ Z5 k: O3 B# M. ~; O; I
案例:
9 W& X0 { G$ ~ session验证) T" o7 d6 H: `
step1 在登录成功之后,在session上绑订一些数据。
5 l; n! \4 J; K% z' V4 n 比如:0 B1 M# f( j7 G, F
session.setAttribute("user",user);- l9 m7 A1 M: x/ z+ f7 I( t* A+ p
step2 在访问需要保护的页面或者资源时,执行
" E# U o5 V/ }6 ^ }! M Object obj = session.getAttribute("user");
) C- v" ~4 s6 d2 X* v! H% X s X 如果obj为null,说明没有登录,一般重定向到
! U. `: C2 {; N: }+ r$ C" J 登录页面。
1 }4 d- R9 _# A4 X$ V; f3 R
. }8 Y" `9 ^: ?5 r- r, i |
|