该用户从未签到
|
状态管理8 A; K( x% n0 f* {; F
1)什么是状态管理3 r {" \; C: p, X8 @, j3 q0 A. {4 W! @) F
将客户端(一般是浏览器)与服务器之间的多次) d2 r$ B% A- A, G# L1 U8 S% O% V
交互当作一个整体来看待,即将多次操作所涉及的
$ q; w. Z z) N) ? 数据记录下来。
! Z4 s% x# h% b& C2 V- P- f 2)怎样进行状态管理) ?! b. l/ X$ V' m
第一种方式,在客户端管理用户的状态
' w$ S) o8 m0 a: j3 @. { (cookie)。8 M2 Y6 P- l( Q
第二种方式,在服务器端管理用户的状态
" c. e1 H: S" ?2 p l (session)。
9 t0 Q3 s! @# R6 ^ 3)cookie
: R9 d2 y& o% W( ? a,什么是cookie?+ l) ~ C! G3 q) @7 J4 X
浏览器在访问服务器时,服务器将一些数据( ?& x4 o% r! y0 G) p& w
以set-cookie消息头的形式发送给浏览器。浏览
) ~* ~1 y0 [( @ 器会将这些数据保存起来。当浏览器再次访问
# `$ f$ \6 ]) i5 U. f% e/ a7 f 服务器时,会将这些数据以cookie消息头的形式. a2 r" S, g8 P( `6 U
发送给服务器。通过这种方式,可以管理用户的
; h) i8 A3 n( P3 ]2 f7 x 状态。
; D& c5 {- r$ m, R8 W b,怎样创建cookie?; k# d1 \% p' ^5 g
Cookie cookie = new Cookie(String name,
8 B- F( a6 X+ |' I* X. e String value);3 g/ U1 R4 H' L$ s3 F8 v' {6 I
response.addCookie(cookie);
$ b( r( Z( R# r2 E0 ~' V c,查询cookie9 g$ q; P4 d; n+ Y* l
//如果没有cookie,则返回null。
. D9 }4 E) K2 S; P& S Cookie[] cookies = request.getCookies(); b: L& e* U# d+ h! [: v; a
String name = cookie.getName();, P& w0 n8 O( u5 {/ b8 h; L8 H
String value = cookie.getValue();
G: `2 n- h9 O) [ d,cookie保存时的编码问题
t! z% E. J/ r. Q$ X0 ~1 |9 B+ R# f6 ? cookie的值只能是ascii字符,如果是中文,
& J. l# y; T- Q& a# m" P/ C: T 需要将中文转换成ascii字符形式。
( j. C8 u/ `8 A% z% y# e 可以使用URLEncoder.encode()方法和
7 x+ {# v8 z5 c( M0 z URLDecoder.decode()方法来进行这种转换。
8 b# R! q1 \) `% b1 y, @6 ]& |, v; j e,cookie的保存时间 ]8 {9 }. U0 b9 A6 Q
cookie.setMaxAge(int seconds);' Y0 ^8 R2 J0 u! E1 p- x" J
seconds > 0:浏览器会将cookie以文件的方式
; T3 M( [/ j0 v: `! P1 l 保存在硬盘上。在超过指定的时间以后,会删除0 k+ Q( a" s9 ^0 U) ]9 b
该文件。0 l; N$ ]3 z* }
seconds < 0:默认值,浏览器会将cookie保存
. b. J1 P6 a' I- A6 z 在内存里面。只有当浏览器关闭之后,才会删除。2 f; U4 O3 _0 b+ g! T
seconds = 0:删除。
& I& ~" e8 }$ H/ g* B* g f,删除cookie7 a, Z. x3 P" O2 y
比如要删除一个name为"username"的cookie。7 J8 X/ j/ }% O3 K A, D3 x
Cookie c = new Cookie("username","");( z( J/ V( C2 \! i, ?/ {
c.setMaxAge(0);5 _ N' h0 {& f) t+ s
response.addCookie(c);: ^5 L% K# Q# X9 b5 m
g,cookie的路径问题
0 ~1 V l* Z) b1 V" l4 K" @ 浏览器在向服务器上的某个地址发送请求时,
) ~ T0 Z- E2 |5 j( ?/ f" F! t 会先比较cookie的路径与向访问的路径(地址)是
E1 |3 {6 J' x* t 否匹配。只有匹配的cookie,才会发送。
: B6 F% |" z2 A! ^2 @ cookie的路径可以通过
* b( _+ F F8 `4 d3 `3 R cookie.setPath(String path)方法来设置。
0 X$ }9 _$ j% s0 m: M5 q0 | 如果没有设置,则有一个缺省的路径,缺省的
M% m4 J7 B* p; c 路径是生成该cookie的组件的路径。; i+ r& g& n3 g# Y, }) _
比如: /appname/addCookie保存了一个cookie,
+ S2 a1 E! L3 ] o; t3 ] 则该cookie的路径就是/appname/addCookie。
2 g% B e9 K" B2 X0 Z: ? 8 i+ a# L( D' P
规则:
1 [4 J. Q" E7 B6 O0 [$ R# m cookie的路径必须是要访问的路径的上层目录: b& A4 G1 }, L& j# v, f
或者是与要访问的路径相等,浏览器才会& Y# G) Y h" h, z
将cookie发送给服务器。$ M, Z' ]5 G/ w* @7 \
* W7 c4 u( o4 F& `. d" T 一般可以设置setPath("/appname"),表示访问; O" f8 _# O$ e
该应用下的所有地址,均会发送cookie。
6 p. X* l, G0 Q h,cookie的限制
@5 Y( _0 U( T' H# a cookie可以禁止9 k4 o6 @! @* `9 g' {1 r
cookie的大小有限制(4k左右)
4 a2 ~% l& r" P5 i$ v; @0 k* |" B2 X cookie的数量也有限制(浏览器大约能保存300个) ! k9 t; m1 n! K1 C6 i5 E0 ?
cookie的值只能是字符串,要考虑编码问题。
& { t% s4 O' V cookie不安全9 f7 f+ c. a. z) `
练习:+ W" y) i$ k% s0 d4 z
写一个Add_FindCookieServlet,该servlet先查询9 k+ P/ o3 g# z: ?& u0 W
有没有一个名叫name的cookie,如果有,则显示
' _8 X6 f' U9 T6 A" t; K0 { 该cookie的值,如果没有,则创建该cookie(# ?3 a) B4 W% w- o9 D: T) n
cookie的名字:name,cookie的值:zs)。
$ S/ ?: d; |2 U, w0 x T' I 8 N* }5 x: {& B! G% F* W- E5 @
( t' R% o2 P0 V! {- {
4)session
% _ P. z5 ]9 b a,什么是session?
! o% ~' J. v$ z& E5 v 浏览器访问服务器时,服务器会创建一个session2 p( w5 D6 ?8 t# |4 Y+ r
对象(该对象有一个唯一的id, 一般称为sessionId)' H/ _8 G1 ^! q+ ], h1 ~, p
。服务器在缺省情况下,会将sessionId以cookie
" S) D, N P( h. N+ m. C u6 ?7 z 机制发送给浏览器。当浏览器再次访问服务器时,
, T% S b Z9 G% ^% d2 W 会将sessionId发送给服务器。服务器依据sessionId& S6 `* N+ x% K! i& V5 }; P ~
就可以找到对应的session对象。通过这种方式,% ^1 R% n: x( L: J; R1 q# ^( a
就可以管理用户的状态。! a% t. x* C0 Y2 \+ `* l F& M
b,如何获得session对象+ A: e0 V; ` M' g' ~6 ]* g
方式一:
: V z' m0 E# `7 N5 ?2 I HttpSession session = 5 F+ l% ~4 Q) ?2 O
request.getSession(boolean flag);" B$ x/ b, ]7 _% P
当flag = true:! G8 n* G" |3 O2 y
服务器会先查看请求中是否包含sessionId,0 T0 S; \" g o5 g6 ?
如果没有,则创建一个session对象。
% p$ W, Q6 ]& [5 U6 X# x6 C8 k 如果有,则依据sessionId去查找对应的
# h2 g; L1 t, m# Q D: v; _ session对象,如果找到,则返回。
0 b* F6 Q% _$ m; r 如果找不到,则创建一个新的session对象。
/ O$ T/ \5 ^8 Z& `8 T+ g 当flag = false:: q9 g. h* D* N" [
服务器会先查看请求中是否包含sessionId,3 D$ o; i# A6 Q! ~/ K3 n4 f
如果没有,返回null。+ v6 E) S1 a$ z& T/ n
如果有,则依据sessionId去查找对应的
6 ]9 y8 [" d. B u session对象,如果找到,则返回。
7 h- M" d( ]; X* H" v+ K3 }6 o; m 如果找不到,返回null。* {0 l. h' N' L- ~0 P; c! p6 @
方式二:9 [7 \ Q) C. n
HttpSession session =
@. v# W& y L request.getSession();
# u5 @# C! [2 O4 Z 与request.getSession(true)等价。% M6 c, E$ @/ U; w& U {* p
c,HttpSession接口提供的一些方法2 R) @! m3 o, f; K5 h1 P R
//获得sessionId。
/ k. J3 C- x! c$ G7 ]4 z6 X String session.getId();
- u% b" X4 }1 M$ ?7 K+ e; i; ^ //绑订数据
8 t9 Y+ d+ c5 u, G& ?' I3 u. q5 d session.setAttribute(
! a7 ? q T) e9 p5 ~0 I String name,Object obj);
; d& w' W: w2 ~$ ?0 M, E( w //obj最好实现Serializable接口(服务器 H7 `0 k) f. p$ }" i
在对session进行持久化操作时,比如钝化
7 `8 T5 C/ t: w9 w" F 、激活,会使用序列化协议)。0 X, v/ I6 Y3 F+ e
Object session.getAttribute(String name);
+ q+ k" T; |; i/ R //如果name对应的值不存在,返回null。 t% q8 u# {( Q$ _% {
session.removeAttribute(String name);
+ r& N( u2 t6 X1 [% X: m+ o d,session超时! }. `5 |& [, u) R/ T1 T
服务器会将超过指定时间的session对象$ k, Q( w( t, ]/ u- y6 H0 N3 T
删除(在指定的时间内,该session对象没有4 z; G: h7 [$ v8 o! B. o, b
使用)。1 g5 k3 Z( G1 @
方式一:$ h4 R j$ Z3 f' w9 a# T
session.setMaxInactiveInterval(
$ A. f( H9 c2 i; w- ]) j int seconds);
- E+ h8 @1 }3 M* }5 o- V 方式二:
9 ]' u- c( N9 s/ k 服务器有一个缺省的超时限制,可以
$ L' R8 I7 C, ?, K 通过相应的配置文件来重新设置。- B( O/ j7 R9 V8 H* J
比如可以修改tomcat的web.xml(1 o- W4 o# v" N; K
tomcat_home/conf下面)。
' P* m1 M/ V9 F# [ <session-config>% u: J$ q- a$ l( z$ o6 R) T+ s6 q
<session-timeout>30</session-timeout>
2 _, L* X5 A( d </session-config>8 T' Z4 y( n5 E( |% D. @
另外,也可以只修改某个应用的web.xml。5 i* [! a8 y$ c$ O0 P! g
e,删除session/ ?8 y# ~0 P q- u
session.invalidate();
/ d% D* Q5 D7 O* U$ ^, b) N 2 g& N, T3 t5 |, ~! `
案例:% j+ b, T% T% |1 E# Z
session验证' s8 K' t9 i G, u. }" J7 Q- }, C
step1 在登录成功之后,在session上绑订一些数据。
3 L* r/ B6 s# A 比如:4 w5 Z8 |& e. O) c' m7 r% W# t
session.setAttribute("user",user); P; o5 ^/ D! ], i
step2 在访问需要保护的页面或者资源时,执行$ P& s8 }" p2 [% G7 L0 @& l1 a2 @$ m
Object obj = session.getAttribute("user");
7 s1 h, H" g9 B! _ 如果obj为null,说明没有登录,一般重定向到8 w0 |7 {* j; X0 J) t j. w# P: b
登录页面。4 \+ X' A% n6 [
7 b1 e+ @* B# I- L% {
|
|