|
该用户从未签到
|
状态管理1 g4 Z4 b: |; a7 R
1)什么是状态管理
) t* X) A! J) H+ { 将客户端(一般是浏览器)与服务器之间的多次$ u# m3 n; t# ~) _' k
交互当作一个整体来看待,即将多次操作所涉及的
% m2 Z5 [) H; [" V, ^2 Q 数据记录下来。5 l8 I$ S: N' G m8 g
2)怎样进行状态管理% L/ o5 Z0 P1 t. G( y: r/ m6 T
第一种方式,在客户端管理用户的状态 Q9 R/ ?. N0 k" d+ c1 Y; v
(cookie)。
; x$ _+ F: y. B; K 第二种方式,在服务器端管理用户的状态- G( h" Z7 A; f- U1 B. m
(session)。
! C/ c: K( E& y4 n; D7 s, w/ T5 _ 3)cookie
4 f4 K$ a8 G7 O- ] H7 x a,什么是cookie?
/ O; G5 U- x" x9 k 浏览器在访问服务器时,服务器将一些数据- k/ A5 F% e9 V
以set-cookie消息头的形式发送给浏览器。浏览
/ ]5 G4 j6 m" w( g 器会将这些数据保存起来。当浏览器再次访问7 {1 m/ I0 M' ]! K3 d( m
服务器时,会将这些数据以cookie消息头的形式
5 S: i$ e0 Y- U, u2 d. `, M 发送给服务器。通过这种方式,可以管理用户的7 d& Q3 T. f" n
状态。
% G. J& d8 E/ W/ ^! i b,怎样创建cookie?
! b, S" K) Y( j( |2 a Cookie cookie = new Cookie(String name,
8 Z9 j( U% ]2 i8 S0 J String value);0 V% L* L; k2 H( A# R7 H
response.addCookie(cookie);
; W [" o$ G9 Q c,查询cookie! }. |1 a. y% v$ E; Q
//如果没有cookie,则返回null。# g2 N! V# U: `+ s/ O
Cookie[] cookies = request.getCookies();
5 G, I5 X# k$ n' G6 d( D+ A9 f/ y String name = cookie.getName();( Z' I7 e( ^, W( i4 K
String value = cookie.getValue();% b9 i$ n! J* P! X$ i# I8 U8 Z+ _1 d
d,cookie保存时的编码问题3 @" a! z6 P* N0 u* o5 H9 {
cookie的值只能是ascii字符,如果是中文,# _9 {9 S' G8 p5 G4 V
需要将中文转换成ascii字符形式。! z) Y5 |5 S; g
可以使用URLEncoder.encode()方法和7 I" W4 L1 i9 R. H1 s: Q
URLDecoder.decode()方法来进行这种转换。4 G/ ~* M6 c' |2 U, s; P) W
e,cookie的保存时间+ Z& M+ s$ I! U
cookie.setMaxAge(int seconds);* ]7 \; E! e% t5 X6 K
seconds > 0:浏览器会将cookie以文件的方式: a$ E% J/ g# I8 O0 Q
保存在硬盘上。在超过指定的时间以后,会删除" @6 x; u% O7 Y! E- f$ @0 Z: e2 ?
该文件。
/ u( x1 L. M, ^% q seconds < 0:默认值,浏览器会将cookie保存
# h+ l# A0 E3 v8 ?4 n2 L- \' Z 在内存里面。只有当浏览器关闭之后,才会删除。
- I6 Y3 E% y' v% s6 [8 X: e; y seconds = 0:删除。
7 ^: J) e9 H( D) K( ~ f,删除cookie" B" P* V" l( a; V' V' I
比如要删除一个name为"username"的cookie。
: ~ V8 C& c3 V; [& b8 p Cookie c = new Cookie("username","");
& G! r5 |8 S0 J7 Z& I0 D. J# z c.setMaxAge(0);. P ^1 E2 J) F; ?
response.addCookie(c);5 _* T5 B- C" e' Z
g,cookie的路径问题# a# D5 K* E8 I
浏览器在向服务器上的某个地址发送请求时,3 ^ C0 p+ W( S
会先比较cookie的路径与向访问的路径(地址)是
& R0 h. B2 z0 j4 b7 K/ Q 否匹配。只有匹配的cookie,才会发送。
# y+ l( h7 |+ o7 o8 t7 R cookie的路径可以通过% k6 q' I1 H2 s0 @9 ]& j+ j5 d
cookie.setPath(String path)方法来设置。/ F( C) \( F' y) }! w# C( @
如果没有设置,则有一个缺省的路径,缺省的& y! E) x- a1 Q" c k; X- ]& Y
路径是生成该cookie的组件的路径。
$ S8 v0 Q) ~: ^7 e/ s0 A 比如: /appname/addCookie保存了一个cookie,7 h+ e% {' n! I* ^
则该cookie的路径就是/appname/addCookie。
0 Y" o) l/ _2 [: L3 n1 S
4 C3 k/ L. s+ a2 u( `5 v 规则:
+ B$ O% i' S3 b Y7 ? cookie的路径必须是要访问的路径的上层目录$ ]: z7 N `8 h, I
或者是与要访问的路径相等,浏览器才会/ `5 e6 R2 J1 | c* `1 X
将cookie发送给服务器。 Z# Q5 y B6 j; H
/ g7 k1 K c+ D3 z4 ^ 一般可以设置setPath("/appname"),表示访问
g1 c7 F2 F' R' h7 i- L+ E 该应用下的所有地址,均会发送cookie。
7 A* o6 h+ n7 `5 `% x' c4 ?7 u h,cookie的限制( c& ?0 [! I( B2 B) D& Q
cookie可以禁止; ~. ]8 g* d; J9 Z9 a6 X6 C
cookie的大小有限制(4k左右)
, a! y/ f- H, Z9 I cookie的数量也有限制(浏览器大约能保存300个)
& h" q& R" a% F9 \ O ?9 e. ~ cookie的值只能是字符串,要考虑编码问题。7 p3 M. `! f* \% K9 `3 g* [. p
cookie不安全
; M! K- E9 l- z/ B# l9 L, t 练习:
: d5 |8 {4 _2 h1 @6 N 写一个Add_FindCookieServlet,该servlet先查询
) G4 s, X5 T' b3 V5 M5 S' L 有没有一个名叫name的cookie,如果有,则显示7 p5 l9 ^9 c# f, _+ Q' v
该cookie的值,如果没有,则创建该cookie(
% X P% q9 S4 Q! r# J) m; b' R$ L cookie的名字:name,cookie的值:zs)。 m6 V; W# A# I U$ f
- Q3 d3 Y9 T+ f$ v
( c- B: ]" c; H; ]0 D9 i 4)session 4 I" p2 C1 ^, k0 O5 ^# y
a,什么是session?/ i, T2 N7 X3 x1 ~, Z* l" w6 G
浏览器访问服务器时,服务器会创建一个session
4 q- u1 m* ^6 _: i Q! Z 对象(该对象有一个唯一的id, 一般称为sessionId)
" h/ M* q+ F! ^+ C 。服务器在缺省情况下,会将sessionId以cookie; H1 L3 W& t3 `2 c* n& c& F
机制发送给浏览器。当浏览器再次访问服务器时,0 H# U. l4 N" v& q0 m$ w8 v
会将sessionId发送给服务器。服务器依据sessionId# B4 u: _( z* e: e( p
就可以找到对应的session对象。通过这种方式,
0 F- R3 Y; z% K3 G3 W1 } 就可以管理用户的状态。; c- B4 s/ u5 m8 u6 y" K/ j
b,如何获得session对象0 x7 _& ~6 c' r1 m
方式一:
& J, H" O& a7 g( b2 v) ] HttpSession session = 3 [+ v( ^+ X# T" F
request.getSession(boolean flag);; U% Z$ E9 a/ o6 l u- ?: n
当flag = true:, k) e& G5 g2 v* j( g0 i- s" _( G
服务器会先查看请求中是否包含sessionId,
" \! S9 O" r. E8 Q. u! h9 g 如果没有,则创建一个session对象。
- j# U* O2 |2 o' Z! |( @ 如果有,则依据sessionId去查找对应的
. n+ D* j3 A7 e( V- {( ? session对象,如果找到,则返回。1 d5 Q# x" l& G5 H
如果找不到,则创建一个新的session对象。! O8 `6 q5 \+ C
当flag = false:
+ B: |* D% Y6 L 服务器会先查看请求中是否包含sessionId,
: A# [$ D( e/ j+ v% L7 T8 a" s5 u 如果没有,返回null。; K, a9 F/ [- ~5 @
如果有,则依据sessionId去查找对应的# ]5 m N8 K7 e- K3 N( k% J
session对象,如果找到,则返回。+ `4 y- T, X9 m2 Z/ z
如果找不到,返回null。
) J( o( I3 w8 U. A% _9 Z' ] 方式二:
$ J; g& B+ n1 L1 N- E HttpSession session =
7 M- c% D4 y6 k; ~; b( |* O request.getSession();
2 O8 c: m' Q. W) q% X 与request.getSession(true)等价。% @8 F$ g; |- X. l; [
c,HttpSession接口提供的一些方法
9 h6 ?, \) w+ a& o9 X. H //获得sessionId。
7 {$ W: }9 i T4 y String session.getId();+ Q q3 ]6 h# P0 t! M; I) m& u
//绑订数据+ ], q2 t3 {( w- K
session.setAttribute(+ i R* Z; Q: o
String name,Object obj);: T% C9 G7 R7 l4 w$ l
//obj最好实现Serializable接口(服务器
4 i/ Q, n) e; c# a 在对session进行持久化操作时,比如钝化& Z$ |5 f& E; V& Y# r& B0 S
、激活,会使用序列化协议)。
3 [1 S2 J |0 P' N Object session.getAttribute(String name);
3 _9 ], |( B4 r5 D9 v //如果name对应的值不存在,返回null。
; l# x& j7 j* `6 b session.removeAttribute(String name);4 B( _# u' I# O" O1 ?. v
d,session超时4 _" m# T3 v/ T( l8 b Z
服务器会将超过指定时间的session对象) \. Y+ y) t7 M
删除(在指定的时间内,该session对象没有
7 f+ ^7 ~ ]$ ]1 J% `, H/ f 使用)。/ ]# z3 J) K2 a$ u0 }. Z/ S. v
方式一:- Y/ E0 c$ V! ]9 p1 t
session.setMaxInactiveInterval(- ~# S v( x7 E8 m. U+ W9 X
int seconds);
/ B& s! A; o# D 方式二:
! |& C. F* A# O) b# I 服务器有一个缺省的超时限制,可以8 _, k% i6 p7 Q' q8 f ]! U
通过相应的配置文件来重新设置。: z4 L+ x0 P5 L
比如可以修改tomcat的web.xml() C$ m- E- w: k$ s: D
tomcat_home/conf下面)。
3 A6 [+ I8 U1 P d4 C9 p4 _ <session-config>/ V- Y: F+ q$ v, D% t
<session-timeout>30</session-timeout>
K) c( Z* }) C: N# I! ~# t </session-config>
+ b6 y( T" C$ F/ Y 另外,也可以只修改某个应用的web.xml。
3 X- ~" h) ~1 F5 @1 z! T e,删除session
) k4 S/ v9 Q5 [4 w# f+ a+ s) g session.invalidate();
V1 M) [3 V, {* i3 S ! U8 K" L8 V) L* g3 K* i
案例:$ C% O% O* v$ u$ d/ K( I$ K i
session验证
) o- G: y7 B- I3 l% E1 T. s! l; _ step1 在登录成功之后,在session上绑订一些数据。
' ` Z, |2 q2 Z! t, Q# F' C$ `3 w- X 比如:
$ K: |' w( }! _5 o" R: E6 R. ], h' G session.setAttribute("user",user);: A* R9 H( q; `* L% l
step2 在访问需要保护的页面或者资源时,执行4 N+ B( |% x2 i, G2 A# c
Object obj = session.getAttribute("user");
! A& Z/ O/ r1 |% g2 w# @8 x 如果obj为null,说明没有登录,一般重定向到9 _! R& t, W& C3 K. z
登录页面。, n8 z' m; R' n, \
9 P' Z& r8 P' j5 s% |$ W U |
|