该用户从未签到
|
状态管理
/ x5 [/ A$ Q/ Z) n# S 1)什么是状态管理
: I9 P+ R0 j9 Z* @+ g 将客户端(一般是浏览器)与服务器之间的多次/ l* S2 v1 X) W. \5 ~8 }- l6 x
交互当作一个整体来看待,即将多次操作所涉及的
! ?+ P& i, v8 T7 }' b 数据记录下来。
) K1 A) H y$ [ a. F- A2 N9 F C 2)怎样进行状态管理
1 w: |6 A& Y; s9 b" ^- K 第一种方式,在客户端管理用户的状态
6 I1 q$ ~5 S+ L; O9 L$ o/ g (cookie)。: }4 U) E, `/ C5 [# j
第二种方式,在服务器端管理用户的状态
/ H/ b u6 z# E4 O (session)。
; U( b+ M4 ~; D 3)cookie
: Q+ V9 {& Z( M( R" j a,什么是cookie?
; }5 ^' J' z, N 浏览器在访问服务器时,服务器将一些数据) \& d9 t7 M& d4 m
以set-cookie消息头的形式发送给浏览器。浏览: q/ F0 n6 r( {
器会将这些数据保存起来。当浏览器再次访问
0 A/ s2 D/ k5 O+ c5 ?, o2 | 服务器时,会将这些数据以cookie消息头的形式3 M! t0 E1 I* p& l
发送给服务器。通过这种方式,可以管理用户的
* J6 H, _" _* C+ Q% n5 ` f 状态。
+ c5 X& p5 g8 t$ `. y4 l# I o b,怎样创建cookie?& `# Z" D+ V9 e" j
Cookie cookie = new Cookie(String name,- N }, c, O' U0 n3 b: a
String value);
5 I; @. b$ U7 J response.addCookie(cookie);+ w, H! ~6 e6 v& C6 z( e2 P
c,查询cookie
8 r% f/ b0 V @/ i //如果没有cookie,则返回null。6 T6 P/ U- ~5 }# g
Cookie[] cookies = request.getCookies();, F: J6 `0 W/ Q- z) @ o
String name = cookie.getName();6 |; x5 Q$ U5 n z( [
String value = cookie.getValue();; z* D! M7 r: _
d,cookie保存时的编码问题
) m& d. l2 s; L0 W! v% d! \. g3 P cookie的值只能是ascii字符,如果是中文,- e* h# V7 `) E7 q' [
需要将中文转换成ascii字符形式。) E, i5 W Z# \& R- K& K- S8 a7 h
可以使用URLEncoder.encode()方法和
$ E1 A' _- h- r4 q URLDecoder.decode()方法来进行这种转换。$ S' ^, r, u) n
e,cookie的保存时间
8 ~$ b" G# [6 n9 y5 Y cookie.setMaxAge(int seconds);! y* O4 h8 O, l2 D8 e- }; e
seconds > 0:浏览器会将cookie以文件的方式
/ \" g* l" K7 c) }6 t* } 保存在硬盘上。在超过指定的时间以后,会删除
& z7 u0 U* ~7 f 该文件。
8 a( m( b6 W. G( C5 Z# R% a seconds < 0:默认值,浏览器会将cookie保存! _4 [& S8 c0 j! D
在内存里面。只有当浏览器关闭之后,才会删除。6 u( L+ O% k7 k
seconds = 0:删除。
3 t$ u: L, J4 G) \7 z3 j f,删除cookie
1 {% B) {, A5 a2 n' L 比如要删除一个name为"username"的cookie。
5 `4 j* k8 F; f7 m1 q1 D Cookie c = new Cookie("username",""); S- _" i3 W/ a
c.setMaxAge(0);
" M/ G7 o8 J: |. W" r" y response.addCookie(c);
0 p7 N. O6 K7 M% r5 ` g,cookie的路径问题
' Y; f$ x! U$ C8 f/ n1 k. F& S8 f 浏览器在向服务器上的某个地址发送请求时,- z' r( e3 D3 `$ c* J: f: K n. b& ~) ~
会先比较cookie的路径与向访问的路径(地址)是 v2 g) E. i6 j% _$ q% x
否匹配。只有匹配的cookie,才会发送。& R; |: U9 g+ d1 H9 {
cookie的路径可以通过
8 U( u* L$ S% D cookie.setPath(String path)方法来设置。
6 z0 A- H6 r5 y& L1 ^5 X( o0 B& l 如果没有设置,则有一个缺省的路径,缺省的! k& l* j# J* e# F; P, o }' n; M0 ~- S
路径是生成该cookie的组件的路径。
1 H' x: ~* P+ U8 a9 m 比如: /appname/addCookie保存了一个cookie,
2 H: s& K B2 Y& X8 c. P 则该cookie的路径就是/appname/addCookie。
: r- y/ k* j" e# X' R0 K# q
7 w7 I+ Q# Z: b6 Z z6 d 规则:
, @) w1 I- f: e! c. d0 E cookie的路径必须是要访问的路径的上层目录0 i) A9 X) l8 t5 P0 _/ ~! m
或者是与要访问的路径相等,浏览器才会
# t( z2 Z8 x- o# V1 O 将cookie发送给服务器。
) U/ w# X8 c/ D P- v& p
1 M$ C4 C; r' P6 v& I% l 一般可以设置setPath("/appname"),表示访问, c- V+ @0 B8 d: l8 A6 s `
该应用下的所有地址,均会发送cookie。3 l( t( x9 c3 u( e- M* d, F
h,cookie的限制8 V( _) b4 R! [1 ^$ x: q
cookie可以禁止
* ?& @$ ^9 [9 S9 F7 h cookie的大小有限制(4k左右)
+ C5 C2 {% M- Q: W cookie的数量也有限制(浏览器大约能保存300个)
5 m! @- q; {( n cookie的值只能是字符串,要考虑编码问题。
7 A/ N0 Y; g9 t- [0 k, l2 q0 F0 O6 z cookie不安全9 ]1 c+ n, T/ c. A# _% |: X
练习:
7 g7 Z/ ~* p) t: X6 ^+ B2 q! X 写一个Add_FindCookieServlet,该servlet先查询
$ K* d% ^( s6 r1 k 有没有一个名叫name的cookie,如果有,则显示# [) R7 E( g5 s: G; A' O6 R& ^) i
该cookie的值,如果没有,则创建该cookie(
6 W( i; z; A6 |1 i cookie的名字:name,cookie的值:zs)。& X! `2 t& F: |0 k, H$ P
6 F: M L4 [8 G8 s8 y9 b
1 K6 x& J6 o3 s4 g w
4)session / U& }0 `! M& o C4 r9 w7 S
a,什么是session?
0 z' X7 j/ X& g g% }: N 浏览器访问服务器时,服务器会创建一个session
+ W$ E; V+ k8 O/ i! r 对象(该对象有一个唯一的id, 一般称为sessionId)2 v$ ?% j; F. d# m
。服务器在缺省情况下,会将sessionId以cookie
0 T- s# {2 G; {( r- M 机制发送给浏览器。当浏览器再次访问服务器时,0 S4 {, }: w$ M( O$ }
会将sessionId发送给服务器。服务器依据sessionId
8 T0 x* V" U8 b 就可以找到对应的session对象。通过这种方式,
+ L' o8 C: E5 W6 g* ]/ t# W 就可以管理用户的状态。0 [% W/ T! P3 `4 J U9 a3 |% q
b,如何获得session对象
- `" _! ]4 k1 i H+ { 方式一:
3 ^8 P) g3 M- y" }+ c/ x! O4 i HttpSession session =
1 w2 k* o& Y2 s' J request.getSession(boolean flag);9 F$ a! i* I! `
当flag = true:
9 W4 y! o& p# u 服务器会先查看请求中是否包含sessionId,
- l$ X$ C! h) z, A; m 如果没有,则创建一个session对象。: P& y/ {" B0 d
如果有,则依据sessionId去查找对应的
2 X7 E' t) H J4 X+ B+ D session对象,如果找到,则返回。
! b) S p8 C! A4 x 如果找不到,则创建一个新的session对象。
2 o! X0 z; c8 R 当flag = false:
% x0 @% o# S% }' z 服务器会先查看请求中是否包含sessionId,
: m/ M ^$ X7 I$ c; O! v, o! e 如果没有,返回null。, D* J' X3 H0 ?) Q( ] W
如果有,则依据sessionId去查找对应的" R: J) C4 v9 o0 G4 w9 z* t
session对象,如果找到,则返回。
+ u! \1 j$ ~# o4 k% F! M/ `, n& t* K 如果找不到,返回null。
8 n6 n I. g: g- T; Q U 方式二:& z3 Y1 |' w# |8 u: P3 C p7 @
HttpSession session =
! G5 w8 ~( P3 Q8 A3 }; O request.getSession();. d& k4 k8 S% @& b+ D" o
与request.getSession(true)等价。7 @: t- M ^2 l$ D& n
c,HttpSession接口提供的一些方法
) L3 x2 r4 I& @5 W. X //获得sessionId。
, w2 D" Q, q* C8 M8 U String session.getId();
0 X# u. l& \/ `6 d1 i //绑订数据7 I5 f2 c o2 n" H6 u0 k
session.setAttribute(5 _. U7 D. c1 g8 C* b3 g
String name,Object obj);. }% B8 _& m, j5 w" N S, z
//obj最好实现Serializable接口(服务器
3 t* }4 {6 v1 Q+ M 在对session进行持久化操作时,比如钝化2 a M5 M1 Y: z8 j
、激活,会使用序列化协议)。 q/ S [; @- p. ?! r
Object session.getAttribute(String name);
& T4 q- R3 r, e1 Z; N/ U //如果name对应的值不存在,返回null。8 m, l9 m; p2 m% L
session.removeAttribute(String name);
* q( X/ \0 {- U+ D# ~5 y' V; U8 f d,session超时8 Y2 ?2 X. p& H0 d
服务器会将超过指定时间的session对象! T6 {' V I( {
删除(在指定的时间内,该session对象没有9 @, T$ x5 y9 U' L# s5 U
使用)。
( D/ y D9 \6 ? 方式一:6 J/ Q) ^* U8 E3 Q. w9 ?3 w, t
session.setMaxInactiveInterval(0 A6 b% t* `" O" `
int seconds);
& q8 w% W$ A5 F3 A1 n1 w 方式二:
% K- t5 a! z. i3 | v 服务器有一个缺省的超时限制,可以
2 w, s4 ?( ?2 y; v4 Z: S4 g/ w 通过相应的配置文件来重新设置。
; D4 i' v% r8 K/ w4 O8 U. a/ w 比如可以修改tomcat的web.xml(' @+ a- t+ C0 `
tomcat_home/conf下面)。
* s, o. X8 h% H& ^ <session-config>+ q0 Z3 q2 @+ p( \! N3 O* a0 U
<session-timeout>30</session-timeout>
7 d/ r& J, o W3 t </session-config>3 l& L% B8 q$ E+ U5 J% U' |
另外,也可以只修改某个应用的web.xml。
) a: t b! l8 b7 G! m& T e,删除session
v" q# O& ? z3 D1 x- a% B9 Z. y session.invalidate();" S3 R) h# ?8 e5 e5 a' D
9 R* Z4 P0 p. F6 k& _3 C
案例:/ {7 i# e7 h( [" Z: M
session验证
, h0 L* j" B- M/ e& Q( N$ ` step1 在登录成功之后,在session上绑订一些数据。
8 ~+ W* b" g/ z& U- P, z9 F 比如:
$ T7 z+ P8 m, {0 ]' `6 ^ session.setAttribute("user",user);
+ h5 ]3 Y0 i; |: l step2 在访问需要保护的页面或者资源时,执行; P! S) g2 A' C e
Object obj = session.getAttribute("user");* R/ {# [* `4 |# k" x
如果obj为null,说明没有登录,一般重定向到6 G# D# {. A! X& O
登录页面。: D4 t" {/ f& D2 c# I
; Z; t! G! X4 w5 t% @0 Y* S6 O
|
|