该用户从未签到
|
2、状态管理6 Z! J8 \1 c. `, {
1)什么是状态管理0 Y7 p) d- a7 {) G9 \: v8 ?
将客户端(一般是浏览器)与服务器之间的多次5 s/ w0 Z: O: [4 T
交互当作一个整体来看待,即将多次操作所涉及的
& Y. F: p- L% t& W& F; y, e8 J8 g 数据记录下来。
6 k2 C# p9 |5 [$ G 2)怎样进行状态管理; `( g" R" j' T" g* E& o+ b
第一种方式,在客户端管理用户的状态1 \- C4 a* V: G- r0 Y
(cookie)。4 k" d) t: [% n1 l$ u6 g
第二种方式,在服务器端管理用户的状态4 s8 z3 u& c l
(session)。% V6 R( }1 n0 D$ T4 ^1 `# O' o6 q
3)cookie
9 [3 v( ?# r* ~& _9 V1 O; } a,什么是cookie?
# J8 y: T3 j" Q1 x6 ]" ? 浏览器在访问服务器时,服务器将一些数据9 o. y2 l7 z. `# u# s
以set-cookie消息头的形式发送给浏览器。浏览
1 c$ \- S! F: Y. M 器会将这些数据保存起来。当浏览器再次访问
! A% E9 n8 L9 d7 R 服务器时,会将这些数据以cookie消息头的形式
* C& ?) \/ m/ t. D- e 发送给服务器。通过这种方式,可以管理用户的: f% z8 |1 O: T$ }( Q( |
状态。
7 L4 O0 R& T9 D# } b,怎样创建cookie?- @% `2 F+ e1 G( v( f* q
Cookie cookie = new Cookie(String name,
$ _) z" ~% B4 O: I String value);5 v- @) M: L; S
response.addCookie(cookie);+ l5 T) ^1 E; O% }
c,查询cookie4 T# }7 h) Q3 Z" x' Y
//如果没有cookie,则返回null。
, E* u8 w: K% V# s+ M8 T6 b+ P Cookie[] cookies = request.getCookies();
6 ^2 i) [0 h, H String name = cookie.getName();2 M+ k7 m% E" Q2 U0 M6 }# Y! Z
String value = cookie.getValue();
; O) N2 x4 w; U6 s d,cookie保存时的编码问题
% m) k7 @9 ^( T; Y; H) Z cookie的值只能是ascii字符,如果是中文," J3 {& P: j# |) w4 v8 T" C0 c
需要将中文转换成ascii字符形式。
" y- u2 r8 K! s( @0 C; P" u. t 可以使用URLEncoder.encode()方法和1 G' p) {9 v8 A) H$ u( E: Y
URLDecoder.decode()方法来进行这种转换。
/ F# |* K, `' Q! s, P8 m& _ e,cookie的保存时间
2 D" ^) A' O3 L! _ cookie.setMaxAge(int seconds);
t8 y9 R0 U: S N# \ seconds > 0:浏览器会将cookie以文件的方式6 y' N6 T- O1 p- x
保存在硬盘上。在超过指定的时间以后,会删除
* V! {0 O7 z" g: @4 y. H# w/ u 该文件。6 o4 q4 V3 ]& y* R- i- v# v& C$ I
seconds < 0:默认值,浏览器会将cookie保存
- Y+ O1 m1 `, e6 \, h 在内存里面。只有当浏览器关闭之后,才会删除。+ K( K7 z( b! G2 b" ?
seconds = 0:删除。
7 l2 Y+ n E- B# E f,删除cookie
" Q6 i- [$ i. S0 G% m9 ] 比如要删除一个name为"username"的cookie。 |( P- Q* X. {$ g7 |
Cookie c = new Cookie("username","");
9 O u; G! J5 m; I c.setMaxAge(0);+ w. c& u# E% Y* ?$ X& E$ z4 ~$ b" r
response.addCookie(c);
: B+ C$ y, Z3 X1 _2 Y& ~ g,cookie的路径问题
. _* P6 C+ i2 Z" i! I 浏览器在向服务器上的某个地址发送请求时,; T5 G0 [, [# J, P
会先比较cookie的路径与向访问的路径(地址)是$ w: |1 w: _+ I: R
否匹配。只有匹配的cookie,才会发送。% ^' I5 E5 x( \0 a# m6 Z* l
cookie的路径可以通过+ Z, m' d( Z# S# o% X4 O8 u
cookie.setPath(String path)方法来设置。
; L$ D6 w: C s9 M6 x! D. @' ]! T; V 如果没有设置,则有一个缺省的路径,缺省的& W6 S3 i' q4 V, r- r, B
路径是生成该cookie的组件的路径。
$ |' i. u- M$ R+ j4 C: |+ T9 N% x7 I. P 比如: /appname/addCookie保存了一个cookie,
$ h7 h4 z- F: U 则该cookie的路径就是/appname/addCookie。
, ]) s+ S+ D$ R) _( b $ e& }. q/ h$ p3 m" t4 m
规则:5 R# K7 [' I% O3 h* X; k P. | f5 _
cookie的路径必须是要访问的路径的上层目录
, g9 c$ k* [( x/ Y 或者是与要访问的路径相等,浏览器才会
$ v( H( n; d8 e1 c; q& ]" M/ _ 将cookie发送给服务器。
. f% f/ x- v$ l9 ? $ X" q G, d. t: S/ V% O/ @* }
一般可以设置setPath("/appname"),表示访问4 }" ^0 O! L- C+ B
该应用下的所有地址,均会发送cookie。
! ~) E2 H& F* F8 Z( ]+ `$ Y h,cookie的限制
4 h0 W$ k. Y! }8 t: L! ~! t cookie可以禁止! M$ H' H; V' r" \6 W# f
cookie的大小有限制(4k左右)
( ^3 M. J# u4 r7 k cookie的数量也有限制(浏览器大约能保存300个) 2 C$ Q6 V% j+ [8 m% C- ~
cookie的值只能是字符串,要考虑编码问题。$ {6 [( g# _* o9 z8 r
cookie不安全
- ?% M% z0 ?* r: R1 q/ w% ^/ s* ~ 练习:
, q# w3 S) @" r 写一个Add_FindCookieServlet,该servlet先查询
( F( ]" q$ o/ P# e- H- A0 L 有没有一个名叫name的cookie,如果有,则显示
! o, _. N) C/ C3 g 该cookie的值,如果没有,则创建该cookie(8 I# C- E+ H5 B& _7 [" k3 A
cookie的名字:name,cookie的值:zs)。
! b3 z* i: b ^* t, u " {3 T4 x( f6 [8 p4 o
: t, V( C# N3 W" p* X1 b6 V 4)session
/ g3 {1 D" c4 U. d& F d% O a,什么是session?
. r4 k5 E) w3 \ }3 u+ u 浏览器访问服务器时,服务器会创建一个session$ T b) k0 n4 k5 D9 Y7 }
对象(该对象有一个唯一的id, 一般称为sessionId)+ X% G% x+ v6 M- J7 ~
。服务器在缺省情况下,会将sessionId以cookie6 @. S0 D- b [# r" |2 ?. d
机制发送给浏览器。当浏览器再次访问服务器时,! ^4 M: P2 q; O3 o, ]
会将sessionId发送给服务器。服务器依据sessionId0 |) X/ Z* P& e4 i- T4 b
就可以找到对应的session对象。通过这种方式,
' E# d# V6 @( k8 c% |: r 就可以管理用户的状态。, I* K4 F7 O! L! c! o" g
b,如何获得session对象. M* f$ F @) [* V* R. U
方式一:
: k8 h; ~% j$ ?( V3 T0 ^- j, Q, ^+ p/ C HttpSession session =
! B1 T9 [2 K' C: h( f- y$ V3 x* H request.getSession(boolean flag);
$ Q: v8 _* h) ?5 q- y$ O 当flag = true:
* ^- [% F2 P: X ^' W: y$ }+ G% R7 ^ 服务器会先查看请求中是否包含sessionId,
. V8 g+ n% \( M/ b( `0 b$ S8 W0 z) S 如果没有,则创建一个session对象。
, _. S. r B& v/ x 如果有,则依据sessionId去查找对应的
) }7 o+ A- ]$ f$ f, a session对象,如果找到,则返回。7 e# P. a: I, D+ r
如果找不到,则创建一个新的session对象。5 E, M F/ p8 l ?/ J0 X: v/ n0 \
当flag = false:
0 X6 A" j% Y$ j0 o' S6 p% @* M 服务器会先查看请求中是否包含sessionId,: ^# @- P6 a! X. v, F3 e
如果没有,返回null。
H, V5 r) E. g 如果有,则依据sessionId去查找对应的* @# W6 @5 r# H# F' R" E- u
session对象,如果找到,则返回。- ? `/ h; e- K8 U% S5 B( _9 ^
如果找不到,返回null。
. V4 x4 Z j2 X( V8 ]; ] 方式二:. L5 f2 z* U; V8 L7 r2 k
HttpSession session = , T5 I/ ?" p1 ^0 @8 {9 k3 H
request.getSession();1 f! w* {+ l: f$ f0 }8 k
与request.getSession(true)等价。
% u2 K, N3 q7 H7 g! A" d c,HttpSession接口提供的一些方法# C# |! o4 n( {6 [/ a/ D9 ^3 C
//获得sessionId。; R$ P0 O6 ^( u* @5 h( F+ [
String session.getId();
) W, I% @$ c# g8 C, t //绑订数据/ F: Z6 a2 _- z1 f2 z) f2 U8 K
session.setAttribute(
; B# |0 K; P2 {" m9 i. P String name,Object obj);
' b7 O: L( E7 c- Y2 B //obj最好实现Serializable接口(服务器. \. C) j3 M, Q! c1 x, ?1 F5 k3 P' {
在对session进行持久化操作时,比如钝化
& r+ }) S* ]% ?8 y" |; j 、激活,会使用序列化协议)。1 f* p- x( m0 u
Object session.getAttribute(String name);9 y0 a% s& S j! p; l$ G; Z8 w
//如果name对应的值不存在,返回null。* T- K' K- q& x* H# J: |9 |9 _
session.removeAttribute(String name);0 R9 t6 F1 O7 {+ C F+ `" {
d,session超时+ [ C- H$ e3 \+ t; h3 N$ ^
服务器会将超过指定时间的session对象
9 K2 f6 K, m0 J: ^4 m 删除(在指定的时间内,该session对象没有
: f1 @! M4 @7 n+ N 使用)。; P. |& D q0 E, j
方式一:0 d( p6 E k0 M I' x$ W; E" ^
session.setMaxInactiveInterval(& B6 N2 g6 _' E% o3 h- v+ @; ~$ V
int seconds);
$ A. e% S6 M! V9 X. h: I% f 方式二:
; {% n' S3 `$ I% n; O. _ 服务器有一个缺省的超时限制,可以- U* x# B5 A9 S8 z7 b Q; ~3 _
通过相应的配置文件来重新设置。! t; J- A4 s5 f/ y& M; C; `2 F
比如可以修改tomcat的web.xml(
; ~) }" c/ {- a* _$ t7 G, @ tomcat_home/conf下面)。
- \; e) w: L) n1 J, Q6 Y& o4 V <session-config>
7 ]" N" |3 c$ h' {5 R <session-timeout>30</session-timeout>6 c3 O3 I% q1 Q$ z7 C0 \0 X
</session-config>
& q& f! j" o# E' t" } 另外,也可以只修改某个应用的web.xml。
$ y( r5 }( u' r e,删除session
0 f' y' n/ o0 } session.invalidate();
2 K( x m3 r: R; ^! { $ F& u) e0 Q( E9 C; \7 ~; B" x
案例:0 G# ?7 V6 U, r" l# Z1 U1 `
session验证
3 }7 F7 i( T% R& \: g step1 在登录成功之后,在session上绑订一些数据。
& @8 I" ^) p! t. z2 T4 O 比如:( Q+ O; S: `+ R# h+ M L: x( o1 K/ `! v
session.setAttribute("user",user);
7 H- l z" U l6 F step2 在访问需要保护的页面或者资源时,执行2 S! ?( N* Y8 l" L Z% ]
Object obj = session.getAttribute("user");
" k' N7 k0 @0 B! [( S 如果obj为null,说明没有登录,一般重定向到
8 [) Q4 t! n4 k9 _, }, D 登录页面。0 B2 @4 I2 I: T% D* V4 D5 ?, {
|
-
总评分: 帮币 + 5
查看全部评分
|