|
该用户从未签到
|
状态管理
! @) j# q$ |. Z% w( P 1)什么是状态管理
) {! V& l; f5 |2 N 将客户端(一般是浏览器)与服务器之间的多次
y/ t+ _' v& N' z, `- I* E+ {$ ? 交互当作一个整体来看待,即将多次操作所涉及的
; E& `% ~9 X' ? 数据记录下来。
% ~- ^! y+ o! y% K) s8 k$ Q% [4 Y 2)怎样进行状态管理& O; n9 f* {/ W; j
第一种方式,在客户端管理用户的状态 i; R2 X- M6 P5 d7 R
(cookie)。
! R. x0 L/ V# U1 a% \ 第二种方式,在服务器端管理用户的状态# r, J6 p, p9 h0 r- V+ C
(session)。
' {( X# p0 R' L8 p) S) W 3)cookie5 F$ E$ D0 j( \/ c$ W1 f2 E+ [
a,什么是cookie?
! a& v4 j* o7 e( v 浏览器在访问服务器时,服务器将一些数据
5 P: D# k! l7 s5 M, i# J& c 以set-cookie消息头的形式发送给浏览器。浏览
8 j4 q" B: e/ X) ?4 k 器会将这些数据保存起来。当浏览器再次访问3 L* K; w2 m/ q8 Y; `; Q3 n
服务器时,会将这些数据以cookie消息头的形式
5 C' w; e) U( C" K, J& ^7 ?! M3 n 发送给服务器。通过这种方式,可以管理用户的9 b; J6 w' [ Q5 H/ t
状态。' x, z/ F, s6 y/ F$ \7 x
b,怎样创建cookie?
& P1 [* I# E" I; r; m Cookie cookie = new Cookie(String name,2 N: K" o3 f) u* a2 q
String value);
. N* D, M' S0 E4 }" r; I response.addCookie(cookie);& [$ | V; @% ^4 p% B/ F w
c,查询cookie
% n; J! h; h% x, t( M) y+ ?2 _ //如果没有cookie,则返回null。& f9 W8 b/ Q+ D& }
Cookie[] cookies = request.getCookies();
8 B- T9 n* ~' T7 @8 m, P String name = cookie.getName();- v- D/ F" o* H7 i2 J$ a0 Q0 E# a
String value = cookie.getValue();5 V8 s& P9 z/ Y/ |$ X5 L& D2 h1 [
d,cookie保存时的编码问题2 w- N. o, e: P4 i( J) x' C
cookie的值只能是ascii字符,如果是中文,
* L3 c- S. R0 ]: f" k 需要将中文转换成ascii字符形式。1 x+ A1 |: N& `2 I+ _* Q
可以使用URLEncoder.encode()方法和
; h& R( [# \& V3 j1 m URLDecoder.decode()方法来进行这种转换。
, m+ Q9 O' I! K, h) ]; x e,cookie的保存时间 |: v: g. y' Q2 K# }: O
cookie.setMaxAge(int seconds);
8 {' F3 Z5 Y4 \* f) l/ L- s$ r seconds > 0:浏览器会将cookie以文件的方式. `0 q* X5 O; m5 x
保存在硬盘上。在超过指定的时间以后,会删除
- U4 N1 d) t" ~, } ^: E 该文件。
5 R, j! c4 [/ F5 W4 k seconds < 0:默认值,浏览器会将cookie保存5 Z, ^' D0 y. |* t, k$ m2 ~( W
在内存里面。只有当浏览器关闭之后,才会删除。$ {/ }0 o6 d- g7 F+ [
seconds = 0:删除。8 ?$ B) |" r, p" F( P
f,删除cookie& W- E- ^. y4 T) q, \* F" w( K
比如要删除一个name为"username"的cookie。2 K% ?- l# c v7 M" c" X l- Q2 C6 \ R
Cookie c = new Cookie("username","");
# w' x# @/ Z! y) \0 J# e c.setMaxAge(0);
% `" [# C3 r( u response.addCookie(c);1 z: O6 _$ _' E1 n
g,cookie的路径问题4 L, O+ b: B T
浏览器在向服务器上的某个地址发送请求时,
# d. l7 `0 V! J: O O; U- K; m6 c% O2 Z 会先比较cookie的路径与向访问的路径(地址)是! b( E w0 F$ E3 P) ?$ P5 ^, Z
否匹配。只有匹配的cookie,才会发送。- X& X" @8 C9 d7 p8 Z r
cookie的路径可以通过# V7 W9 T& ~0 I& t
cookie.setPath(String path)方法来设置。
+ K7 d$ ~( c5 } 如果没有设置,则有一个缺省的路径,缺省的3 D5 a. R; [/ U
路径是生成该cookie的组件的路径。
+ ?, b5 ]) x: R6 j; Q4 b& _5 O 比如: /appname/addCookie保存了一个cookie, G5 _2 r2 U: S2 U9 X* @2 T; _1 C5 C
则该cookie的路径就是/appname/addCookie。5 S: [2 d8 M: f
5 m' K4 c3 Y9 I! S
规则:
5 h1 b0 N( D6 ~! P) a- T cookie的路径必须是要访问的路径的上层目录
! U) D6 G2 c% M# D 或者是与要访问的路径相等,浏览器才会. Q6 @" Z# P9 d; g
将cookie发送给服务器。- \0 E1 v7 e9 ?1 q1 P5 d
" Y$ M8 d3 V& p! E" [; y6 n9 R
一般可以设置setPath("/appname"),表示访问
- g+ r) Q) \" w2 R; \ 该应用下的所有地址,均会发送cookie。
5 N( K, E; h$ U h,cookie的限制/ w8 g7 ?, \2 X- m% I& m0 b
cookie可以禁止" w" q) i. I8 Y
cookie的大小有限制(4k左右)
7 `* _1 v" q8 _) e, t1 r4 B cookie的数量也有限制(浏览器大约能保存300个) - }- c: }$ M/ p) X
cookie的值只能是字符串,要考虑编码问题。
]- b( [$ n$ Z0 H2 r ]" s, c! v! m cookie不安全
& s l9 p( S0 u9 @1 W3 e; k; K( Y 练习:* j" c* P8 s$ V+ x4 a$ _
写一个Add_FindCookieServlet,该servlet先查询3 r' g; S; y+ z3 M f9 x
有没有一个名叫name的cookie,如果有,则显示
5 Q# J- e. M% `2 u; ` 该cookie的值,如果没有,则创建该cookie(5 E t: A% {$ G7 }
cookie的名字:name,cookie的值:zs)。
; x2 \2 Z/ L B& ]6 D7 d
+ ` H$ c+ L+ S4 U
1 X$ b1 B. N, p3 H$ c9 m7 A 4)session 0 ^ L7 s& ?& F! \
a,什么是session?2 O& G; m$ D t }, k
浏览器访问服务器时,服务器会创建一个session' Q% o9 U2 `* G' `' [
对象(该对象有一个唯一的id, 一般称为sessionId) h! C( U o" B, h
。服务器在缺省情况下,会将sessionId以cookie
2 O3 h5 t3 \0 N 机制发送给浏览器。当浏览器再次访问服务器时,# h0 T/ b3 h8 O$ r/ g
会将sessionId发送给服务器。服务器依据sessionId$ ~6 v" \5 R# {0 H6 p: W, d' u
就可以找到对应的session对象。通过这种方式,
( F" p. O' }* q. T& m 就可以管理用户的状态。- m( f, {1 c9 j" j u2 F& \2 s
b,如何获得session对象
; b8 S" b# `! L D) `+ T 方式一:
$ x5 f* k( Z! w HttpSession session =
" Q6 ?& _: o: ` {- \4 i& X request.getSession(boolean flag);
. X6 B; ~4 l, G* m5 r 当flag = true:$ l% I! X5 d: f4 U6 T3 z/ K
服务器会先查看请求中是否包含sessionId,
* d# C1 ~! g7 G 如果没有,则创建一个session对象。
8 k# h' j7 N: ` 如果有,则依据sessionId去查找对应的
# S4 u& |) [' Z$ p A session对象,如果找到,则返回。, R) O. E& q' j" q: M
如果找不到,则创建一个新的session对象。: _9 T/ A5 o E& E
当flag = false:0 o0 L2 h- B; D4 F! U, k
服务器会先查看请求中是否包含sessionId,- ^% u3 R% d' j3 ?/ S [
如果没有,返回null。
6 o: `* v$ e2 u. h+ d* j 如果有,则依据sessionId去查找对应的" U1 l( s; d1 e) H
session对象,如果找到,则返回。
+ e, O& T; p4 J; Q( E 如果找不到,返回null。
# V# ]$ ]. l/ Y p9 p1 k 方式二:
) I/ y2 c# U, R2 j3 E. h HttpSession session = % R6 l9 G# J* J' C) ?
request.getSession();
5 Y# w: @ c+ u4 w" c5 g3 ^ 与request.getSession(true)等价。+ G L3 G, r& ?' ~; E) z7 l
c,HttpSession接口提供的一些方法5 D o7 m! |: u5 E) E! ~. S
//获得sessionId。
7 k1 F) r4 ]0 L$ D4 N$ Y) h' E String session.getId();0 w7 p9 y1 u! T* Q
//绑订数据 p3 v! q ?8 l. G- r1 R* [9 e+ R" ?( g) c
session.setAttribute(. d* C5 Y+ K- t [& K- o. b
String name,Object obj);
- X. R. p$ |) B$ s1 G //obj最好实现Serializable接口(服务器
! V0 A" z$ s8 f2 j 在对session进行持久化操作时,比如钝化
% W4 x$ ? J# S" o; x; q7 s 、激活,会使用序列化协议)。2 q# S _% q; d5 ~6 c/ x" o u
Object session.getAttribute(String name);; Q9 m- f) F; P9 O. _0 |$ L
//如果name对应的值不存在,返回null。: I# g1 b& }$ H+ G7 T) y1 L
session.removeAttribute(String name);" B/ K# J+ t V
d,session超时
' F7 q3 P+ S3 t- X 服务器会将超过指定时间的session对象) T! q) j w0 Z0 i) d% M4 w
删除(在指定的时间内,该session对象没有
$ b9 c+ d. \ b2 ^9 x 使用)。
- a7 |1 Z0 I/ `. X2 w 方式一:% W h" b) e9 e" x8 p
session.setMaxInactiveInterval(
: O% u9 E8 o( P. k int seconds);2 P+ Y( P1 M* A x7 t/ Z
方式二:
- P& j3 E3 d ]4 T, u+ ^( o, T' ] 服务器有一个缺省的超时限制,可以
' X9 M1 j# h) _6 U% d) J 通过相应的配置文件来重新设置。
, g1 Q5 W Q- K! P' Z, S. l' B 比如可以修改tomcat的web.xml(( R! O( G. }7 Z& l5 ?$ ~- \
tomcat_home/conf下面)。0 K5 q: g8 O( J- h% V
<session-config>
4 n7 c1 X, X7 N5 q <session-timeout>30</session-timeout>) y, z& Y( r4 c; V9 S( ^$ i4 I
</session-config>0 m/ z. G. c0 o0 F
另外,也可以只修改某个应用的web.xml。
6 f5 B' ?* G, O$ L9 b3 e e,删除session
% u) H9 x% b. Z' P+ b4 V session.invalidate();
; E5 j# p4 t- z/ Y& S; @
. M; k/ T* o3 `5 t/ R( a \ 案例:3 s% K& p% Z# M6 j- N
session验证. s3 M" J E6 r
step1 在登录成功之后,在session上绑订一些数据。7 W7 U1 e' e, L+ i8 E
比如:
0 ^3 `1 S5 n9 T; F session.setAttribute("user",user);
7 K. j2 ^+ C$ B- ?# x6 F9 n2 D4 D step2 在访问需要保护的页面或者资源时,执行- Z. m+ w( Y5 k0 z1 \# g. u
Object obj = session.getAttribute("user");& w" g6 V, ]% T
如果obj为null,说明没有登录,一般重定向到, f* g1 V+ i& t% d
登录页面。
: e. _2 q& e0 D7 X4 v# R. N
* D5 S' O( X' k0 f ~9 B |
|