该用户从未签到
|
状态管理
7 w0 G, Y8 W Q! C3 [% f7 s 1)什么是状态管理
2 v' Q$ s3 Z% B" `, r 将客户端(一般是浏览器)与服务器之间的多次, C- X6 R" G8 d6 h1 j
交互当作一个整体来看待,即将多次操作所涉及的
$ [7 D$ n D8 W8 U, j 数据记录下来。
5 u' t7 i# p; [8 Y0 w4 L: y 2)怎样进行状态管理, q* F/ ]( M5 K) p5 B. T
第一种方式,在客户端管理用户的状态
% n- k& e/ D: ~& K" M8 I (cookie)。
' s, Z) t" h7 ]8 u. T( P1 Z% E/ ~/ e 第二种方式,在服务器端管理用户的状态7 J( f0 P* }. u' Q0 [) g
(session)。) l) f5 p' G1 ~7 E! f: l1 Q. ^. r
3)cookie
8 v- J/ [1 Q+ y" P& d a,什么是cookie?
( I! }" @1 a" K4 [& V0 b- C 浏览器在访问服务器时,服务器将一些数据# n2 Q9 V; s/ i4 Y# e
以set-cookie消息头的形式发送给浏览器。浏览! f' p( a0 }! F. p9 D& q( W
器会将这些数据保存起来。当浏览器再次访问9 }% C! m) d3 \; [5 ]& D0 l
服务器时,会将这些数据以cookie消息头的形式0 k+ l/ x3 ^' z$ @
发送给服务器。通过这种方式,可以管理用户的1 Q- A9 _) e* ~7 N5 t
状态。
+ U& ~9 S0 r) \8 { b,怎样创建cookie?
& t1 r3 J: ~% `. M1 v+ ~) r Cookie cookie = new Cookie(String name,
; I1 ]2 u" q: z String value);
; ^+ l8 s- H" {! K$ r2 H response.addCookie(cookie);
+ i! i9 I3 b9 o% Z! Z% b c,查询cookie7 Q, {2 u. a# b$ D/ ?) E
//如果没有cookie,则返回null。
6 Q; ?$ w# g+ ]+ S N: E Cookie[] cookies = request.getCookies();
; T4 A& q9 r0 N. M String name = cookie.getName();- z1 B& k" q; s. H$ g; l0 \
String value = cookie.getValue();
, S' x9 f: X( A9 H$ O- b d,cookie保存时的编码问题& ?$ n) {* S% v2 y) Z4 L
cookie的值只能是ascii字符,如果是中文,, ?+ I! O' Q1 e$ G3 Q% U/ E
需要将中文转换成ascii字符形式。
4 V( b- v, B2 q+ ] 可以使用URLEncoder.encode()方法和$ A; r* k- |4 H# R4 ~. s
URLDecoder.decode()方法来进行这种转换。
, I- }* J# e9 }' C e,cookie的保存时间3 A4 C- w" E( n' X) u# `
cookie.setMaxAge(int seconds);
8 g6 v8 ]3 y: b0 f0 @6 O) V seconds > 0:浏览器会将cookie以文件的方式- r. s0 Y" V- Q$ s
保存在硬盘上。在超过指定的时间以后,会删除
* c j+ m0 {: I7 t% @ 该文件。: s& t. V; \7 r8 V6 ~' b9 W4 [
seconds < 0:默认值,浏览器会将cookie保存/ V' d/ E( ^. J% t
在内存里面。只有当浏览器关闭之后,才会删除。
, I/ w% y, i' U; L- s4 @9 F, H2 w$ s seconds = 0:删除。! y* a. z9 S4 Y& {. D# W
f,删除cookie, H5 J/ B/ k6 \. M% z) w$ b) ?
比如要删除一个name为"username"的cookie。
0 E) y3 i8 K' T* D2 a" A+ \ Cookie c = new Cookie("username","");
: u. b6 D6 A0 q: o6 Y c.setMaxAge(0);
7 N3 }' c+ w# B% E% E7 r9 G response.addCookie(c);2 x7 I. g/ u4 b% ~$ e0 M4 U$ o2 m
g,cookie的路径问题$ Y: d! ?: h; S$ j' s s
浏览器在向服务器上的某个地址发送请求时,* ^' ]( w# N" g: p
会先比较cookie的路径与向访问的路径(地址)是
8 ^# U. q: ^5 c. |: f 否匹配。只有匹配的cookie,才会发送。
1 h6 w6 y2 `% y. y cookie的路径可以通过4 F7 }1 f% w9 d
cookie.setPath(String path)方法来设置。
! ~3 e" h1 Z. ` 如果没有设置,则有一个缺省的路径,缺省的
9 M9 Q* f" J' G 路径是生成该cookie的组件的路径。
% c1 b* n i( |) r% V 比如: /appname/addCookie保存了一个cookie,% t3 [- e$ B, m
则该cookie的路径就是/appname/addCookie。
$ T" ?; V; u- a% {! V- q! A : t2 V, X, M$ @/ \+ d
规则:
# L1 @' }9 ]; A! |+ h- U cookie的路径必须是要访问的路径的上层目录8 J" ]$ [, }) i7 l( O7 Q9 ?
或者是与要访问的路径相等,浏览器才会
/ R" E ]* C4 V( n9 j& E9 | 将cookie发送给服务器。0 L( U: K7 [" O
) N/ [' \; z) L2 l* a* \( ~
一般可以设置setPath("/appname"),表示访问
# ?( ^2 |, W. K 该应用下的所有地址,均会发送cookie。+ Z$ Q9 {# W/ H1 j3 k8 _ m
h,cookie的限制
6 \' H0 U0 N; F0 k! Z+ k, N# k cookie可以禁止
& _ U6 I( M: O6 h cookie的大小有限制(4k左右)
! @+ x; ^) [8 j7 a) v cookie的数量也有限制(浏览器大约能保存300个) * y3 r- c: b( I) ^, B Z7 |
cookie的值只能是字符串,要考虑编码问题。8 p# }4 h) @# w" k" M( D& j) s
cookie不安全; R$ r1 R3 i0 c- G5 }' P
练习:3 i) B9 [, ^0 Y: j0 @
写一个Add_FindCookieServlet,该servlet先查询
* \% E: V6 g! ] 有没有一个名叫name的cookie,如果有,则显示
5 N$ y0 d$ Q/ I: j9 S 该cookie的值,如果没有,则创建该cookie($ r' a1 K5 r9 X$ a: j
cookie的名字:name,cookie的值:zs)。7 l$ l/ |+ v' a" ~6 W. k/ B% ]3 i% o
: J! {- \* V; f$ o, Z) B G$ H 2 S: ?/ u4 R+ h$ H/ W9 `
4)session
" X' f0 H, c Q8 G2 z1 g a,什么是session?
2 M3 N% B$ M" E; W% Y8 }+ K 浏览器访问服务器时,服务器会创建一个session6 M4 R% r6 }+ z7 m2 |& I+ K
对象(该对象有一个唯一的id, 一般称为sessionId); _$ o& ], N, m
。服务器在缺省情况下,会将sessionId以cookie2 |3 r! K( Z5 q# l; V8 `
机制发送给浏览器。当浏览器再次访问服务器时,
4 d9 k+ j4 d8 H& M& h3 K2 t. K 会将sessionId发送给服务器。服务器依据sessionId
8 u& K7 m: C9 \; u$ s7 H" e/ M 就可以找到对应的session对象。通过这种方式,
) d0 M1 `1 Z. z4 y+ E$ B' t 就可以管理用户的状态。
# r' B) }3 T+ Q. E8 ?" ^ b,如何获得session对象
0 d, C) M& j0 m. {8 Q 方式一:+ B7 c( E( {+ }8 C3 T4 G* W* }0 X
HttpSession session = * U( C1 u: `4 Q2 r$ d
request.getSession(boolean flag);6 m! F; u3 n% G8 K }- j5 }. [
当flag = true:: F4 ^2 f4 J' W. I
服务器会先查看请求中是否包含sessionId,
% w9 R1 k, y( F, h 如果没有,则创建一个session对象。
4 z, `" l, w* |5 L) H0 |4 D" R 如果有,则依据sessionId去查找对应的
8 F6 `7 l( u# R; k# J0 \1 f* H# M session对象,如果找到,则返回。* v' P8 u6 T/ M, Z
如果找不到,则创建一个新的session对象。
6 K% p' }, u2 C) B, G* J 当flag = false:( ?5 ~" e- v0 V
服务器会先查看请求中是否包含sessionId,
* w6 m# o8 B% Z x0 \" }- a. q; o. k 如果没有,返回null。: i1 x6 @) \& M# t1 S7 C! ?3 G
如果有,则依据sessionId去查找对应的
3 e9 g* b% k6 b: m session对象,如果找到,则返回。
$ I( q. a2 H" r( d 如果找不到,返回null。 L0 z2 F5 ]8 w7 X: c" N
方式二:
$ }0 g3 g1 [2 W! h e1 b HttpSession session =
: @; l# w9 ^+ S6 h6 M# D' C request.getSession();6 c, f, Q f7 }! o7 u
与request.getSession(true)等价。
: f* a0 r) D* \/ m" v5 g3 x, q+ H c,HttpSession接口提供的一些方法: [. b! Q9 \+ w8 A! ~! q. \
//获得sessionId。# C8 `8 J# o8 b
String session.getId();
" i9 I; j/ l# D2 ]7 t8 [# a' L //绑订数据
! P7 b, j: u# W# q1 v9 } session.setAttribute(. `8 S/ W# L% a3 W% l* ^
String name,Object obj);
8 e" h4 s- e8 _ //obj最好实现Serializable接口(服务器! @, p1 E( s1 G3 K
在对session进行持久化操作时,比如钝化
6 t/ Y' u) a, K! A! z; _ 、激活,会使用序列化协议)。! p# [+ ^4 U- Y& A! R* n. T0 t
Object session.getAttribute(String name);
8 K! c+ K& j% g) M$ }, U2 r' { //如果name对应的值不存在,返回null。7 R: Q+ ^# W+ i" e. X
session.removeAttribute(String name);
# L+ h) M6 W) Q; { d,session超时
* [9 ~ }$ [9 ?# W, t 服务器会将超过指定时间的session对象7 ~( Z: _- \8 G+ W4 H+ Y; Y! |% l. u
删除(在指定的时间内,该session对象没有
4 B2 Q5 H% `' F6 F7 v% V7 Y3 P8 \ 使用)。3 w) h9 \, @& W4 [+ \6 N
方式一:% \3 R% ~0 S$ \$ n
session.setMaxInactiveInterval(# H0 C5 h/ Z7 W. a7 M" k- {
int seconds);
- N; k' S0 _ x8 Z) @% i 方式二:
( @" W; {( q+ ^3 N" D 服务器有一个缺省的超时限制,可以
3 ~! Q7 X5 S: Q9 g% Z; d 通过相应的配置文件来重新设置。4 `' F% c9 E& Q" Y( o& @
比如可以修改tomcat的web.xml(0 _. t9 I( I8 L8 O
tomcat_home/conf下面)。% s: o+ i: F( S
<session-config>& g1 X+ Q9 o7 H7 V
<session-timeout>30</session-timeout>
! T' h+ g6 x+ ]" w </session-config>( v7 K/ U( n0 Y1 Q6 R( \( ~" ^
另外,也可以只修改某个应用的web.xml。
" j1 ~6 a9 a% Y) g. b6 \ e,删除session
6 F7 X9 T" t' h3 z! f session.invalidate();
& E3 l& a. j! U% C6 E6 c: v% I; w : z( B# _" J$ g: A c D6 d- G
案例:) f0 q! w% x0 s5 j8 S$ o9 _
session验证
, J" `* J0 r) D. i* S- d step1 在登录成功之后,在session上绑订一些数据。
1 V8 w( c% y1 V8 c8 Q X 比如:
( i3 x2 [9 [ i7 p" C session.setAttribute("user",user);/ B5 g& J. k. X0 L2 q
step2 在访问需要保护的页面或者资源时,执行/ |3 k) x5 R( v
Object obj = session.getAttribute("user");
6 p% o4 u7 F2 w) I1 P5 J; W1 c4 W 如果obj为null,说明没有登录,一般重定向到
S. ^' }( U; l8 v, U 登录页面。
d9 Y2 L0 y8 Q2 l9 B& B k7 J% j$ I
|
|