|
该用户从未签到
|
状态管理
) \) U+ I- M: I% `9 O+ I 1)什么是状态管理
; T! h. y( {# G 将客户端(一般是浏览器)与服务器之间的多次
8 X4 D: x4 N* I& e- x0 X 交互当作一个整体来看待,即将多次操作所涉及的
4 q8 n# X5 q) L5 c1 a& ^ 数据记录下来。4 v' D% L% N, |0 }
2)怎样进行状态管理
% b; I( I% |# c8 s0 S2 `1 A' A$ n" o 第一种方式,在客户端管理用户的状态
T0 D. u9 [9 m( {. Q$ x: D (cookie)。# [- g+ X: {# u( |7 s1 D' b
第二种方式,在服务器端管理用户的状态) {4 p$ U# k7 Q& S m
(session)。
- v# Z- K+ l, w5 ? 3)cookie
0 g) V$ }0 U' ~$ I9 w9 v a,什么是cookie?
. p8 C) b; a% y 浏览器在访问服务器时,服务器将一些数据
@: _ M" _' w% r" L4 q! a C/ C 以set-cookie消息头的形式发送给浏览器。浏览
; E, A4 `6 T$ P0 R! ]9 F4 x8 [ 器会将这些数据保存起来。当浏览器再次访问
( {; V5 H7 d4 v" ]+ P 服务器时,会将这些数据以cookie消息头的形式& p- L/ K. `, q8 |
发送给服务器。通过这种方式,可以管理用户的
. `/ r3 T3 [$ x( B3 N b 状态。 g9 Q8 Y; x0 E) N+ h
b,怎样创建cookie?
, v+ r) b- V7 | Cookie cookie = new Cookie(String name,0 X* f% R( }+ ~ d
String value);; G* c1 G7 F) p0 K6 g0 f2 O5 [
response.addCookie(cookie);8 K9 k1 c" `5 O& V$ k) w
c,查询cookie
, R- |4 _+ q3 }: p8 } //如果没有cookie,则返回null。
2 i) l7 P( O6 E4 N8 _% K Cookie[] cookies = request.getCookies();3 k6 a( a' D/ a' ^+ [- Q: t) \) W& {
String name = cookie.getName();9 p& E" ~$ ^! p
String value = cookie.getValue();# c: @5 \$ F3 w. [7 w1 B/ D9 s
d,cookie保存时的编码问题0 M7 b" E6 S+ I5 Z! h
cookie的值只能是ascii字符,如果是中文,
" t: m: k: M/ N% u: k 需要将中文转换成ascii字符形式。
3 s; H9 ?: E* B; s& Q' O d7 x( q1 v+ j 可以使用URLEncoder.encode()方法和
- Q% y" C& p4 e1 l% C2 ^, j URLDecoder.decode()方法来进行这种转换。
: N% J: t5 l9 |% a; R& {# Z) a; b e,cookie的保存时间
9 a) u" N4 y# V9 }6 s0 E6 ]3 s cookie.setMaxAge(int seconds);
9 b& n7 N9 p% N1 g2 k seconds > 0:浏览器会将cookie以文件的方式
% q0 _! O. d( t( H2 U" a" W 保存在硬盘上。在超过指定的时间以后,会删除 }3 Y& } ^9 Q# p/ G0 f
该文件。# }& p* \: f' w8 x/ t
seconds < 0:默认值,浏览器会将cookie保存! Y, |( H1 b" q6 E, X
在内存里面。只有当浏览器关闭之后,才会删除。
: U5 J) i. |1 c C$ c seconds = 0:删除。
: g" y; Q( Q) n, p3 Q$ l7 Q3 A f,删除cookie
6 u: R: l2 X( N7 Z 比如要删除一个name为"username"的cookie。
+ Q; F2 Z. a8 H- ?# M- Y4 ^ Cookie c = new Cookie("username","");1 W' p5 k2 R8 \+ Q; R( w1 D' x
c.setMaxAge(0);2 X* P6 [% i# n- Q a: E) {0 c4 o
response.addCookie(c);. |1 j- b% z" u$ X: p
g,cookie的路径问题
3 J2 M8 I2 }4 [( U! c4 c9 x 浏览器在向服务器上的某个地址发送请求时,6 Q( S2 Y; U) h! x% v' M* x ?
会先比较cookie的路径与向访问的路径(地址)是' |& c. I) _& {9 B% j9 I) T: W0 ?) \
否匹配。只有匹配的cookie,才会发送。
: }8 c9 }0 T- X: i cookie的路径可以通过
% B8 R5 ?9 R; _* G$ _5 P cookie.setPath(String path)方法来设置。
) b8 W' l" k7 x5 q3 y- c 如果没有设置,则有一个缺省的路径,缺省的
: ]( ?* u7 k% `7 _6 E 路径是生成该cookie的组件的路径。, }- ^4 H& N8 c) _' d8 T4 v
比如: /appname/addCookie保存了一个cookie,
7 H2 u" G: _4 ^ 则该cookie的路径就是/appname/addCookie。
/ [# Z4 _$ @6 C2 i {3 L# z 3 O9 x ^; b+ b( l% j4 Y
规则:
! Y0 ~8 D$ d S+ H/ F cookie的路径必须是要访问的路径的上层目录* e' }7 W J d2 p8 Q
或者是与要访问的路径相等,浏览器才会* V0 A* a% ?+ F U+ u( b8 d
将cookie发送给服务器。2 X6 O( ~8 V, l+ O2 L9 G+ s! H5 S
t3 q0 J& C' b8 n/ q 一般可以设置setPath("/appname"),表示访问
5 ]6 l/ C9 X6 b' Q4 }2 z0 h6 a. { 该应用下的所有地址,均会发送cookie。5 K) i7 X# d! A+ t R1 k) A3 z
h,cookie的限制5 N* r; X q* _
cookie可以禁止
' a3 E* H- e+ k0 |" ^0 G$ Z cookie的大小有限制(4k左右). F, D5 N9 @, h* W+ y& ]/ q# O! V/ L8 S
cookie的数量也有限制(浏览器大约能保存300个)
% P/ T5 N( P5 T4 l1 Y9 E5 ~& } cookie的值只能是字符串,要考虑编码问题。
$ n \; u5 j. ~, M G. T# d cookie不安全
% f7 p( a8 F) u4 c 练习:3 ~0 M/ A% z/ d6 k0 X- l
写一个Add_FindCookieServlet,该servlet先查询' R. L% F n/ L, F/ h, J2 x
有没有一个名叫name的cookie,如果有,则显示
( E9 [( [% j% J 该cookie的值,如果没有,则创建该cookie(
' {* S0 n7 R' B cookie的名字:name,cookie的值:zs)。! k9 Z- r: G9 I3 Z2 K" i
9 B7 C# I: u7 m9 T. Y/ ?
; N: I1 x3 \0 ]8 j 4)session - X ^. S' l+ S
a,什么是session?
: a0 x0 G: H( x% t 浏览器访问服务器时,服务器会创建一个session
+ I' C, v) X6 q1 S) s. o( w 对象(该对象有一个唯一的id, 一般称为sessionId). T8 k3 `1 K0 G- ^# W5 C: Z% C
。服务器在缺省情况下,会将sessionId以cookie: c0 p, m0 x. y: F6 z' {
机制发送给浏览器。当浏览器再次访问服务器时,) y/ \) N9 Q' [, A1 U$ W, b/ J* s
会将sessionId发送给服务器。服务器依据sessionId
+ C" A7 j, x& o 就可以找到对应的session对象。通过这种方式,: T+ B8 r: v$ K3 n. E) p
就可以管理用户的状态。
( m1 ~2 ^9 x4 p$ l' H b,如何获得session对象
, V5 Y7 ]% }' x* Z0 u0 W! C 方式一:( x4 A, O: O) h' g
HttpSession session = / k) H% O# ^6 H& P7 |- M8 B3 {( y' Y
request.getSession(boolean flag);
5 |' {+ U$ @& E8 T; G7 M( V( k: I 当flag = true:5 K- G( t0 [1 ^3 J8 r8 u
服务器会先查看请求中是否包含sessionId,
2 o# u$ k; o3 c) x- k 如果没有,则创建一个session对象。
; _5 g# D' g) p 如果有,则依据sessionId去查找对应的
: |2 W6 H. a- \" I$ m, a) X session对象,如果找到,则返回。
! ]! p+ E1 G: E$ y 如果找不到,则创建一个新的session对象。
: f$ Y( `8 J% T( {/ w 当flag = false:
9 x$ b, L! S" H5 Y3 Y1 D. { 服务器会先查看请求中是否包含sessionId,
2 A* N$ a& I/ K: A7 p& n 如果没有,返回null。
0 b7 m5 O0 T! m& ]4 Q N 如果有,则依据sessionId去查找对应的1 Y3 E( f! p" g& s) S: w1 r0 h
session对象,如果找到,则返回。, V3 T' ^/ K( E$ e0 [$ E4 V
如果找不到,返回null。
" T) u: D8 v6 |0 s 方式二:
4 \4 n( @1 c( C' [ HttpSession session = 1 q% H# W$ Y; Q; k+ L2 u0 _
request.getSession();
2 }0 d3 K5 i2 `& v, D4 T 与request.getSession(true)等价。
. i1 T5 {& s6 R' g' f" E c,HttpSession接口提供的一些方法
$ t$ I) i' i6 R( z- U% l* v //获得sessionId。
6 V3 m8 ?. c1 T4 y9 \2 E String session.getId();# j o+ A6 e4 z: q! ?
//绑订数据% i: m0 B" w7 a
session.setAttribute(/ R+ Y! p6 n! r" H. U
String name,Object obj);
5 \, p& G) U6 Y //obj最好实现Serializable接口(服务器
! C; v0 F$ L1 u2 z9 e) i1 ] 在对session进行持久化操作时,比如钝化8 U5 X( w2 i1 i9 |$ n# N
、激活,会使用序列化协议)。4 k9 @/ a# s2 g7 `
Object session.getAttribute(String name);
( U; H( d$ {" ]. o0 U. } //如果name对应的值不存在,返回null。
0 c% [# O! _" b! b% O session.removeAttribute(String name);$ r9 x+ ~; S- Q `: p9 @
d,session超时
3 q# ^( w( j! n 服务器会将超过指定时间的session对象
6 z) u- K, w7 T) ?8 L5 s0 q 删除(在指定的时间内,该session对象没有 l4 m1 d- V, [! T
使用)。' V% n/ e9 B* x: i% K# N7 w3 P
方式一:
2 E1 o9 F V+ A" f( q! N4 X- A9 H$ x session.setMaxInactiveInterval(
% S) _ W% r: |/ A0 O8 \) l int seconds);
, H& P2 e4 `$ T) k( x0 I! B 方式二:5 y. _6 M" J2 l
服务器有一个缺省的超时限制,可以4 `: W4 l, N$ Q! T: h9 S" x
通过相应的配置文件来重新设置。
7 {6 h+ o! M- L5 E/ A+ w) D7 t 比如可以修改tomcat的web.xml(
+ W7 |. g! R( h6 `( ^7 C2 l3 N1 I9 J tomcat_home/conf下面)。
) B+ N4 t9 r1 ~/ ^4 u <session-config>& }- i9 Y, C- B% b O0 m& P/ }
<session-timeout>30</session-timeout>9 U5 M' R) C0 N; n; y, s
</session-config>
+ e/ [6 ?$ ^: D3 H 另外,也可以只修改某个应用的web.xml。
, ?1 ]: f9 {3 S# d' o9 z e,删除session
( `) i( K( x+ G0 u6 p) ?6 d" c session.invalidate();
! a5 \7 y! L; M$ M3 _3 U 2 q& W9 M1 ^+ _, x6 }$ {
案例:8 t, F* z; z; i, ?4 e; T
session验证
1 W" F( M5 X) | k) ^! o step1 在登录成功之后,在session上绑订一些数据。! c# D+ F+ M5 c3 [
比如:
9 ?( x' ^) s& B5 h session.setAttribute("user",user);
7 f" o, I R3 a8 S/ I5 d step2 在访问需要保护的页面或者资源时,执行2 ~. S& Y' e; y3 k, H+ n
Object obj = session.getAttribute("user");' c5 N3 _+ j0 g0 m
如果obj为null,说明没有登录,一般重定向到
& W% _. M- Z# ~0 i 登录页面。
5 g. J; y+ l" z2 |2 R: ?8 p4 z: A: [; l
|
|