该用户从未签到
|
状态管理8 T8 U+ J' M' C9 v" ]% j7 V7 @
1)什么是状态管理: P% w. ]2 z4 a+ }! ]
将客户端(一般是浏览器)与服务器之间的多次
. s* X% J4 L7 c' {5 @& r; Z 交互当作一个整体来看待,即将多次操作所涉及的
" a1 p. P' y& g9 C9 M2 @! S 数据记录下来。
8 }# O$ {, m1 Z1 k- L7 s# x% {: s+ b2 n 2)怎样进行状态管理
h' g5 i4 T/ u0 m 第一种方式,在客户端管理用户的状态$ w; U4 n4 }& o2 ~& K
(cookie)。
- K' S/ t6 J: @# ~: y, t9 K 第二种方式,在服务器端管理用户的状态! M. z* N3 G a2 e$ x: M7 u
(session)。- O$ H" j! E' Q" l3 n0 J6 h' F
3)cookie$ i0 c( I7 m& c' M0 c& F3 t
a,什么是cookie? Q! |3 e( Z2 L6 _/ w7 Z! `' ?
浏览器在访问服务器时,服务器将一些数据; m2 a% A1 j7 u9 _6 R
以set-cookie消息头的形式发送给浏览器。浏览
1 R# Y q& V8 N 器会将这些数据保存起来。当浏览器再次访问( B# n9 U+ |0 }/ Q
服务器时,会将这些数据以cookie消息头的形式. m8 @5 p0 X- d7 m! S
发送给服务器。通过这种方式,可以管理用户的, b8 A1 [* G! { h4 g4 A* D
状态。/ W# U" C8 d% h$ g& g/ T
b,怎样创建cookie?
! P2 k4 D8 f" [! m$ v Cookie cookie = new Cookie(String name,, B3 }: E- U6 f( L+ X% }
String value);
4 [$ g/ b# l8 \! Z! g response.addCookie(cookie);
( J: I/ u: d, p0 R# U6 b N9 { c,查询cookie4 c# m0 O6 Y% z
//如果没有cookie,则返回null。( f" I- u5 u: n' S& f* \( v( \) C
Cookie[] cookies = request.getCookies();
& ~" u" V$ w% g5 r String name = cookie.getName();
+ ~5 H, H0 m6 F5 p: _3 E# I# m9 S String value = cookie.getValue();, [& Z. Z6 }" `! h+ o
d,cookie保存时的编码问题
+ E# v( {0 S6 ?! {8 | cookie的值只能是ascii字符,如果是中文," O. ?/ r, R/ U/ ^- Q, v5 P
需要将中文转换成ascii字符形式。
" X# t6 Z+ ~, D: U1 x2 \ 可以使用URLEncoder.encode()方法和. i3 i$ C1 J; d9 l; G
URLDecoder.decode()方法来进行这种转换。
" T, A9 A9 k, k6 K$ Q% I+ J$ Z- m e,cookie的保存时间2 d% A1 N: F6 c) O+ a# C
cookie.setMaxAge(int seconds);
0 n. P" U' @1 i6 R9 d1 w# X6 h3 Y4 j seconds > 0:浏览器会将cookie以文件的方式0 M' P2 K, Y/ O( t' F! B" f3 n" B
保存在硬盘上。在超过指定的时间以后,会删除
; [9 N. T& h" U$ b 该文件。! ?8 t. S! M" X6 t
seconds < 0:默认值,浏览器会将cookie保存
- h* R% R- ~: d+ ~% | 在内存里面。只有当浏览器关闭之后,才会删除。
" W. k8 H& g# u- K seconds = 0:删除。# ~# F6 b( y5 F: m- J5 p
f,删除cookie! x" _3 k. N% x
比如要删除一个name为"username"的cookie。
" \! v0 t1 K6 |7 b/ Z Cookie c = new Cookie("username","");
& g& ^ [6 P9 M7 b c.setMaxAge(0);) v. D: O& o% ?
response.addCookie(c); Z# V0 C" h4 A" a7 \
g,cookie的路径问题 @0 Q- o+ D; V. _6 G- b7 u- w9 H5 I
浏览器在向服务器上的某个地址发送请求时,
* k' g& o3 B$ F' J 会先比较cookie的路径与向访问的路径(地址)是, I4 E% Y n& f% F
否匹配。只有匹配的cookie,才会发送。
$ W2 ]/ w! w+ Q8 s! G# {% j cookie的路径可以通过 q' H5 q* d4 X4 d3 b H6 }
cookie.setPath(String path)方法来设置。, C" ^- g0 O7 i$ I
如果没有设置,则有一个缺省的路径,缺省的
9 c8 A/ {8 P/ K, Q. M% G1 c% i# b$ ? 路径是生成该cookie的组件的路径。1 k' N1 ~! r7 I+ l$ P; f, f$ U7 x
比如: /appname/addCookie保存了一个cookie,5 f9 \9 P7 n4 I; w* J; m9 R
则该cookie的路径就是/appname/addCookie。
4 ]- c, T1 Y+ l; L
* w9 }# }) ? j/ c: k 规则:
9 q0 P( W: A) b9 C+ C& o cookie的路径必须是要访问的路径的上层目录2 C2 s5 j* o! u: R
或者是与要访问的路径相等,浏览器才会0 v* z6 S" v) [: e% n# e
将cookie发送给服务器。
8 b7 H4 G; Q9 {, ` 2 V" O4 J) O- {6 K
一般可以设置setPath("/appname"),表示访问
+ K/ h2 ]( {: [6 i3 A 该应用下的所有地址,均会发送cookie。
9 O, `% `$ i" u9 t; y6 V, i1 c h,cookie的限制5 S0 S3 m& V, P* P0 V, g
cookie可以禁止
* T; S/ _5 y1 Q1 H1 D cookie的大小有限制(4k左右)' P3 |7 D. M, M- S' \
cookie的数量也有限制(浏览器大约能保存300个) + d6 J+ R% l. {. O
cookie的值只能是字符串,要考虑编码问题。5 p# j" |# c! o, y
cookie不安全' a& |6 G5 \( b% u' c. K+ z
练习:! P0 u( g& Q; q. x+ r" I
写一个Add_FindCookieServlet,该servlet先查询( G3 P) J2 D5 E: A9 f
有没有一个名叫name的cookie,如果有,则显示4 [6 @0 H- [ A4 c! L8 z
该cookie的值,如果没有,则创建该cookie(2 ~) {+ {! O) O
cookie的名字:name,cookie的值:zs)。
1 y" n( N) n4 G+ H
7 @; u5 w Z% y" \$ d ) B. u" m( S; B
4)session 1 q& D& L6 n' u5 _% ~
a,什么是session?
@/ B' c4 m, q T# B9 k 浏览器访问服务器时,服务器会创建一个session
$ ?. g1 t2 S+ J6 S# j 对象(该对象有一个唯一的id, 一般称为sessionId)
/ ]& U5 i9 r' E2 C) W6 k' Y 。服务器在缺省情况下,会将sessionId以cookie6 H/ @. h' f4 f; O* E4 @8 z+ V
机制发送给浏览器。当浏览器再次访问服务器时,
3 Z4 A2 {+ \" Y0 p# k 会将sessionId发送给服务器。服务器依据sessionId* H% p2 ~# C1 n+ k# g
就可以找到对应的session对象。通过这种方式,9 m7 D" {" g t( {8 N. [6 @
就可以管理用户的状态。. O2 {2 v) P/ g- C, l* o: ?
b,如何获得session对象- A+ O: E" J' ?" F+ \9 `
方式一:9 c2 ^* \. _- I! n) s9 F
HttpSession session = 4 T+ Z1 A `. t j8 f
request.getSession(boolean flag);
/ U. r4 ~# I3 V, P! {" ] 当flag = true:7 w0 z' K; O* ]; N% Q' B5 c
服务器会先查看请求中是否包含sessionId,& S6 a0 |* o% M( H
如果没有,则创建一个session对象。
2 F: y0 B! r2 q, w: o 如果有,则依据sessionId去查找对应的
6 h! e" y/ M4 [3 z7 r9 } session对象,如果找到,则返回。; ]9 k" B8 \; D1 j5 t: g0 Q( z% i
如果找不到,则创建一个新的session对象。! ^5 H1 a8 U# O7 C* D6 V
当flag = false:4 ?5 G3 A* e4 E# ~" n9 ^
服务器会先查看请求中是否包含sessionId,) _' [7 }! M" }9 e3 H+ u& H: L7 y
如果没有,返回null。
$ F: o) G; y7 U$ u 如果有,则依据sessionId去查找对应的7 _2 l/ q/ n7 d W: w
session对象,如果找到,则返回。
# Q8 ]' g- ~4 b; B 如果找不到,返回null。, g7 d- v B. ]& s3 L, S
方式二:' X# X ^. d h5 w
HttpSession session = + v' D: r# U) |
request.getSession();# R0 b& Z6 n5 s7 p6 n) J7 f0 |( y
与request.getSession(true)等价。9 K8 L% A) P5 |/ S. J
c,HttpSession接口提供的一些方法% d6 R# h1 X3 S- ^+ ?) X
//获得sessionId。) q* `9 T3 y* F, \/ t
String session.getId();
. \) i$ v, x* W7 i //绑订数据3 m7 F" ^0 P: b C9 n5 Q! k
session.setAttribute(
% Z" H7 g' S" v% |4 g ~% i String name,Object obj);
. b0 a% r2 h& M4 g' G //obj最好实现Serializable接口(服务器- Y8 T1 a8 |# u/ n$ M" V
在对session进行持久化操作时,比如钝化: J1 K6 R9 w* F6 D
、激活,会使用序列化协议)。% b, D6 f" l% [
Object session.getAttribute(String name);) r+ D) f" Q, N' D
//如果name对应的值不存在,返回null。, A: }; `+ A. u$ a! [' \2 e0 q
session.removeAttribute(String name);
5 F! B A% l3 N% U$ p; i6 ?% H d,session超时' ?. f; Y9 ~; W
服务器会将超过指定时间的session对象
- J% i, @! Y; |% g E: ` 删除(在指定的时间内,该session对象没有
5 z) Z8 `& U# f# a1 h6 W4 C2 \- | 使用)。
/ C& T# }& x. b& R; Q 方式一:
& ?; d8 I/ p7 x6 }/ O6 U$ h+ T session.setMaxInactiveInterval(
3 H6 Y" [1 J8 ~+ E0 S int seconds);
* m$ [( k: i9 f" l9 c9 s" R. _ 方式二:
8 ?, l, F' V' r2 m% \1 z1 s 服务器有一个缺省的超时限制,可以
0 O1 g% L) Y2 [/ v 通过相应的配置文件来重新设置。
) U& x0 P( }. _/ V3 s+ h* S/ Q% z3 V 比如可以修改tomcat的web.xml(. @) C. v% a! m) P: L4 Y
tomcat_home/conf下面)。- w/ V4 h3 s$ h6 r& U X
<session-config>' O$ S3 @3 \* J3 ]6 \
<session-timeout>30</session-timeout>
! T! c9 c, j: ^8 V8 {7 W- a8 V ^ </session-config>
( E8 q# }, Z" C 另外,也可以只修改某个应用的web.xml。4 H ^* |. H/ [
e,删除session# r7 s2 k4 B7 _% S8 X; j1 q2 y
session.invalidate();
. n4 p5 l8 c5 L* g, h
; Y4 N9 g6 F0 M 案例:
7 W9 N- O; v3 q! Z" }# s; Y session验证
( q! S2 N; y0 L, T$ @ step1 在登录成功之后,在session上绑订一些数据。
) s+ b) R* S S; ]5 p5 a( R3 b 比如:2 ?6 @9 [; U0 B: L0 G3 W
session.setAttribute("user",user);
8 @, _& f# ]7 m$ l4 G5 s step2 在访问需要保护的页面或者资源时,执行
. M8 E2 ^8 H4 M4 e: s* {" q0 T Object obj = session.getAttribute("user");
0 O9 s/ r6 J- I7 Y8 m& E, O/ \( j 如果obj为null,说明没有登录,一般重定向到 _! U1 b5 n+ {
登录页面。* W8 K9 K" E& \' B
! U4 h4 r. p# O- c
|
|